akonadi: import 1.13.0

This commit is contained in:
Ivailo Monev 2015-09-23 09:37:02 +00:00
parent 273587f5ac
commit 438d2bd635
445 changed files with 59528 additions and 0 deletions

6
akonadi/.gitignore vendored Normal file
View file

@ -0,0 +1,6 @@
# Ignore the following files
*~
*.[oa]
*.kdev4
.swp.*
.*.swp

1
akonadi/.kateconfig Normal file
View file

@ -0,0 +1 @@
// kate: space-indent on; indent-width 2; remove-trailing-space on; remove-trailing-space-save on;

1
akonadi/.krazy Normal file
View file

@ -0,0 +1 @@
EXCLUDE i18ncheckarg,syscalls,qclasses,qmethods,crashy,strings,cpp

3
akonadi/.reviewboardrc Normal file
View file

@ -0,0 +1,3 @@
REVIEWBOARD_URL = "https://git.reviewboard.kde.org"
TARGET_GROUPS = "akonadi"
REPOSITORY = "akonadi"

88
akonadi/AUTHORS Normal file
View file

@ -0,0 +1,88 @@
Maintainer:
- Dan Vrátil <dvratil@redhat.com>
Main Authors:
- Volker Krause <vkrause@kde.org>
- Till Adam <adam@kde.org>
- Tobias Koenig <tokoe@kde.org>
- Kevin Krammer <kevin.krammer@gmx.at>
Contributors:
- Albert Astals Cid <aacid@kde.org>
- Àlex Fiestas <afiestas@kde.org>
- Alex Merry <kde@randomguy3.me.uk>
- Alexander Neundorf <neundorf@kde.org>
- Allen Winter <winter@kde.org>
- Andras Mantia <amantia@kde.org>
- Andreas Cord-Landwehr <cola@uni-paderborn.de>
- Andreas Gungl <a.gungl@gmx.de>
- Andreas Hartmetz <ahartmetz@gmail.com>
- Andreas Holzammer <andreas.holzammer@kdab.com>
- Andreas Pakulat <apaku@gmx.de>
- Andre Heinecke <aheinecke@intevation.de>
- Aurélien Gâteau <agateau@kde.org>
- Bertjan Broeksema <broeksema@kde.org>
- Bjoern Ricks <bjoern.ricks@googlemail.com>
- Carlo Segato <brandon.ml@gmail.com>
- Christian Ehrlicher <Ch.Ehrlicher@gmx.de>
- Christian Mollekopf <chrigi_1@fastmail.fm>
- Cédric Villemain <cedric@2ndQuadrant.com>
- Christian Schaarschmidt <schaarsc@gmx.de>
- Christophe Giboudeaux <cgiboudeaux@gmail.com>
- Constantin Berzan <exit3219@gmail.com>
- Dario Freddi <drf@kde.org>
- David Faure <faure@kde.org>
- David Jarvie <djarvie@kde.org>
- Dirk Mueller <mueller@kde.org>
- Frank Osterfeld <frank.osterfeld@kdemail.net>
- Grégory Oestreicher <greg@kamago.net>
- Gregory Schlomoff <gregory.schlomoff@gmail.com>
- Guy Maurel <guy.maurel@kde.org>
- Harald Fernengel <harry@kdevelop.org>
- Helio Chissini de Castro <helio@kde.org>
- Igor Trindade Oliveira <igor_trindade@yahoo.com.br>
- Ingo Kloecker <kloecker@kde.org>
- Jaime Torres <jtamate@gmail.com>
- Jakub Stachowski <qbast@go2.pl>
- Jesper Thomschütz <jesperht@yahoo.com>
- Jesse Lee Zamora <xtremek2008@aim.com>
- Kevin Ottens <ervin@kde.org>
- Kitware, Inc., Insight Consortium.
- Laurent Montel <montel@kde.org>
- Leo Franchi <lfranchi@kde.org>
- Loic Marteau <loic.marteau@gmail.com>
- Manolo Valdes <nolis71cu@gmail.com>
- Marc Mutz <mutz@kde.org>
- Marco Martin <notmart@gmail.com>
- Matthias Kretz <kretz@kde.org>
- Michael Drueing <michael@drueing.de>
- Michael Jansen <kde@michael-jansen.biz>
- Mike Arthur <mike@mikemcquaid.com>
- Milian Wolff <mail@milianw.de>
- Mirko Boehm <mirko@kde.org>
- Nicolás Alvarez <nicolas.alvarez@gmail.com>
- Nicolas Lécureuil <nlecureuil@mandriva.com>
- Olivier Trichet <nive@nivalis.org>
- Patrick Spendrin <ps_ml@gmx.de>
- Pavel Heimlich <tropikhajma@gmail.com>
- Pino Toscano <toscano.pino@tiscali.it>
- Raphael Kubo da Costa <rakuco@FreeBSD.org>
- Rex Dieter <rdieter@math.unl.edu>
- Robert Zwerus <arzie@dds.nl>
- Rolf Eike Beer <eike-kernel@sf-tec.de>
- Romain Pokrzywka <romain@kdab.net>
- Sebastian Sauer <mail@dipe.org>
- Sebastian Trueg <sebastian@trueg.de>
- Sergio Martins <iamsergio@gmail.com>
- Shaheed Haque <srhaque@theiet.org>
- Stephen Kelly <steveire@gmail.com>
- Szymon Stefanek <pragma@kvirc.net>
- Thomas Friedrichsmeier <thomas.friedrichsmeier@ruhr-uni-bochum.de>
- Thomas McGuire <mcguire@kde.org>
- Timo Hummel <timo.hummel@sap.com>
- Tom Albers <toma@kde.org>
- Torgny Nyblom <kde@nyblom.org>
- Vadim Zhukov <persgray@gmail.com>
- Will Stephenson <wstephenson@kde.org>
- Wolfgang Rohdewald <wolfgang@rohdewald.de>
- Yury G. Kudryashov <urkud.urkud@gmail.com>

View file

@ -0,0 +1,44 @@
# AkonadiConfig.cmake is generated by CMake from akonadi/AkonadiConfig.cmake.in.
# Any changed value in this file will be overwritten by CMake.
@PACKAGE_INIT@
# set the akonadi version number
set(AKONADI_VERSION_MAJOR @AKONADI_VERSION_MAJOR@)
set(AKONADI_VERSION_MINOR @AKONADI_VERSION_MINOR@)
set(AKONADI_VERSION_PATCH @AKONADI_VERSION_PATCH@)
set(AKONADI_VERSION @AKONADI_VERSION@)
set(AKONADI_VERSION_STRING "@AKONADI_VERSION_STRING@")
# set AKONADI_DEFINITIONS
set(AKONADI_USE_STRIGI_SEARCH FALSE) # backward compat, remove eventually
set(AKONADI_DEFINITIONS "@AKONADI_DEFINITIONS@")
# set the directories
if(NOT AKONADI_INSTALL_DIR)
set(AKONADI_INSTALL_DIR "@CMAKE_INSTALL_PREFIX@")
endif(NOT AKONADI_INSTALL_DIR)
set_and_check(AKONADI_BIN_DIR "@PACKAGE_BIN_INSTALL_DIR@")
set_and_check(AKONADI_CONFIG_DIR "@PACKAGE_CONFIG_INSTALL_DIR@")
set_and_check(AKONADI_DBUS_INTERFACES_DIR "@PACKAGE_DBUS_INTERFACES_INSTALL_DIR@")
set_and_check(AKONADI_DBUS_SERVICES_DIR "@PACKAGE_DBUS_SERVICES_INSTALL_DIR@")
set_and_check(AKONADI_INCLUDE_DIR "@PACKAGE_INCLUDE_INSTALL_DIR@")
set_and_check(AKONADI_LIB_DIR "@PACKAGE_LIB_INSTALL_DIR@")
set_and_check(AKONADI_SHARE_DIR "@PACKAGE_SHARE_INSTALL_PREFIX@")
set_and_check(AKONADI_XDG_MIME_INSTALL_DIR "@PACKAGE_XDG_MIME_INSTALL_DIR@")
# the exports file exports
set(AKONADI_TARGET_PREFIX @AKONADI_TARGET_PREFIX@)
# Load the exported targets.
if(NOT TARGET Akonadi__akonadiprotocolinternals)
get_filename_component(_currentDir "${CMAKE_CURRENT_LIST_FILE}" PATH)
include("${_currentDir}/AkonadiTargetsWithPrefix.cmake")
endif()
macro(_akonadi_Set_Lib_Vars _prefix _lib)
set(AKONADI_${_prefix}_LIBRARIES ${AKONADI_TARGET_PREFIX}${_lib})
endmacro()
_akonadi_set_lib_vars(COMMON akonadiprotocolinternals)

370
akonadi/CMakeLists.txt Normal file
View file

@ -0,0 +1,370 @@
project(Akonadi)
cmake_minimum_required(VERSION 2.8.8 FATAL_ERROR)
# where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked
set(CMAKE_MODULE_PATH "${Akonadi_SOURCE_DIR}/cmake/modules")
# Enable CMake's Automoc
set(CMAKE_AUTOMOC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
# Used to report the packages we found
include(FeatureSummary)
############### Build Options ###############
include(CTest)
include(CTestConfig.cmake)
option(AKONADI_BUILD_TESTS "Build the Akonadi unit tests." TRUE)
option(AKONADI_BUILD_QSQLITE "Build the Sqlite backend." TRUE)
option(INSTALL_QSQLITE_IN_QT_PREFIX "Install the QSQLite plugin in QT_PLUGIN_DIR" FALSE)
option(STATIC_LIBRARY "Build Akonadi as a static library." FALSE)
option(QT5_BUILD "Build Akonadi using the Qt5 framework" FALSE)
option(WITH_SOPRANO "Build with Soprano support. Needed for Nepomuk search integration." FALSE)
if(NOT DEFINED DATABASE_BACKEND)
set(DATABASE_BACKEND "MYSQL" CACHE STRING "The default database backend to use for Akonadi. Can be either MYSQL, POSTGRES or SQLITE")
endif()
if(AKONADI_BUILD_TESTS)
enable_testing()
endif()
############### CMake Macros ###############
include(InstallSettings)
include(CheckFunctionExists)
include(CheckIncludeFiles)
include(CMakePackageConfigHelpers)
############### CTest options ###############
# Set a timeout value of 1 minute per test
set(DART_TESTING_TIMEOUT 60)
# CTestCustom.cmake has to be in the CTEST_BINARY_DIR.
# in the KDE build system, this is the same as CMAKE_BINARY_DIR.
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/CTestCustom.cmake ${CMAKE_CURRENT_BINARY_DIR}/CTestCustom.cmake COPYONLY)
############### The Akonadi version (used in AkonadiConfig.cmake) ###############
set(AKONADI_VERSION_PATCH "0")
# Raise the minor version if we're building Akonadi using Qt5
if(QT5_BUILD)
set(AKONADI_VERSION_MAJOR "1")
set(AKONADI_VERSION_MINOR "79")
set(AKONADI_SOVERSION "2")
else ()
set(AKONADI_VERSION_MAJOR "1")
set(AKONADI_VERSION_MINOR "13")
set(AKONADI_SOVERSION "1")
endif()
set(AKONADI_VERSION "${AKONADI_VERSION_MAJOR}.${AKONADI_VERSION_MINOR}.${AKONADI_VERSION_PATCH}")
set(AKONADI_VERSION_STRING "${AKONADI_VERSION}")
# If Git is installed and a '.git' directory is found,
# we append the Git revision to AKONADI_VERSION_STRING
if(EXISTS "${Akonadi_SOURCE_DIR}/.git")
find_package(Git)
if(GIT_FOUND)
message(STATUS "Found git: ${GIT_EXECUTABLE}")
execute_process(COMMAND ${GIT_EXECUTABLE} rev-parse --short HEAD
WORKING_DIRECTORY ${Akonadi_SOURCE_DIR}
OUTPUT_VARIABLE akonadi_git_revision
OUTPUT_STRIP_TRAILING_WHITESPACE)
set(AKONADI_VERSION_STRING "${AKONADI_VERSION_STRING} (revision: ${akonadi_git_revision})")
endif()
endif()
############### Macros ###############
macro(SET_DEFAULT_DB_BACKEND)
set(_backend ${ARGV0})
if("${_backend}" STREQUAL "SQLITE")
set(AKONADI_DATABASE_BACKEND QSQLITE3)
set(AKONADI_BUILD_QSQLITE TRUE)
else()
if("${_backend}" STREQUAL "POSTGRES")
set(AKONADI_DATABASE_BACKEND QPSQL)
else()
set(AKONADI_DATABASE_BACKEND QMYSQL)
endif()
endif()
message(STATUS "Using default db backend ${AKONADI_DATABASE_BACKEND}")
endmacro()
#### DB BACKEND DEFAULT ####
set_default_db_backend(${DATABASE_BACKEND})
############### Find what we need ###############
#### Qt 4 and 5 ####
if(QT5_BUILD)
find_package(Qt5Core REQUIRED)
find_package(Qt5Gui REQUIRED)
find_package(Qt5Widgets REQUIRED)
find_package(Qt5Sql REQUIRED)
find_package(Qt5Network REQUIRED)
find_package(Qt5Xml REQUIRED)
find_package(Qt5DBus REQUIRED)
find_package(Qt5Test REQUIRED)
include("cmake/modules/ECMQt4To5Porting.cmake")
include_directories(${QT_INCLUDES}) # TODO: Port away from this.
if(CMAKE_VERSION VERSION_LESS 2.8.9)
message(FATAL_ERROR "Akonadi Qt 5 build requires at least CMake version 2.8.9")
endif()
if (Qt5_POSITION_INDEPENDENT_CODE)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
endif()
set(QT_QTTEST_LIBRARIES Qt5::Test)
else()
set(QT_USE_IMPORTED_TARGETS TRUE) # Qt 4 only
set(QT_MIN_VERSION 4.8.0) # Qt 4 only
find_package(Qt4 REQUIRED)
include(${QT_USE_FILE})
endif()
if(STATIC_LIBRARY)
set(LIBRARY_TYPE STATIC)
set(AKONADI_STATIC_LIBS ON)
message(STATUS "Building Akonadi as a static library")
else()
set(LIBRARY_TYPE SHARED)
endif()
#### Soprano ####
if(WITH_SOPRANO)
set(SOPRANO_MIN_VERSION 2.7.56)
find_package(Soprano)
set_package_properties(Soprano PROPERTIES
URL "http://soprano.sourceforge.net"
DESCRIPTION "Storage of semantic data"
TYPE REQUIRED
PURPOSE "Soprano is needed for the Nepomuk search backend"
)
endif()
#### SMI ####
set(SMI_MIN_VERSION "0.20")
find_package(SharedMimeInfo ${SMI_MIN_VERSION})
set_package_properties(SharedMimeInfo PROPERTIES
URL "http://freedesktop.org/wiki/Software/shared-mime-info"
DESCRIPTION "File types database and utilities"
TYPE REQUIRED
)
#### XSLTProc ####
find_program(XSLTPROC_EXECUTABLE xsltproc)
if(NOT XSLTPROC_EXECUTABLE)
message(FATAL_ERROR "\nThe command line XSLT processor program 'xsltproc' could not be found.\nPlease install xsltproc.\n")
endif()
#### Boost ####
# In CMake >= 2.8.6, FindBoost.cmake tries to find BoostConfig.cmake which is
# not compatible with CMake's FindBoost. Disable this function.
set(Boost_NO_BOOST_CMAKE TRUE)
find_package(Boost COMPONENTS program_options)
set_package_properties(Boost PROPERTIES
URL "http://www.boost.org"
DESCRIPTION "The Boost C++ Libraries"
TYPE REQUIRED
PURPOSE "Akonadi requires the Boost C++ libraries (program_options)"
)
# should be handled by FindBoost.cmake -> cmake bug #8335
if(WIN32 AND NOT Boost_USE_STATIC_LIBS)
add_definitions(-DBOOST_DYN_LINK)
add_definitions(-DBOOST_PROGRAM_OPTIONS_DYN_LINK)
endif()
#### Sqlite ####
# If Sqlite is the default backend, it cannot be optional.
if("${DATABASE_BACKEND}" STREQUAL "SQLITE")
set(SQLITE_TYPE "REQUIRED")
else()
set(SQLITE_TYPE "OPTIONAL")
endif()
if(AKONADI_BUILD_QSQLITE)
set(SQLITE_MIN_VERSION 3.6.23)
find_package(Sqlite ${SQLITE_MIN_VERSION})
set_package_properties(Sqlite PROPERTIES
URL "http://www.sqlite.org"
DESCRIPTION "The Sqlite database library"
TYPE ${SQLITE_TYPE}
PURPOSE "Required by the Sqlite backend"
)
endif()
############### Compilers flags ###############
option(CMAKE_COMPILE_GCOV "Build with coverage support." FALSE)
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_C_COMPILER MATCHES "icc" OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang"))
set(_ENABLE_EXCEPTIONS -fexceptions)
# more aggressive warnings and C++11 support
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-long-long -std=iso9899:1990 -Wundef -Wcast-align -Werror-implicit-function-declaration -Wchar-subscripts -Wall -Wextra -Wpointer-arith -Wwrite-strings -Wformat-security -Wmissing-format-attribute -fno-common")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -Wnon-virtual-dtor -Wundef -Wcast-align -Wchar-subscripts -Wall -Wextra -Wpointer-arith -Wformat-security -fno-common")
# debugfull target
set(CMAKE_CXX_FLAGS_DEBUGFULL "-g3 -fno-inline" CACHE STRING "Flags used by the C++ compiler during debugfull builds." FORCE)
set(CMAKE_C_FLAGS_DEBUGFULL "-g3 -fno-inline" CACHE STRING "Flags used by the C compiler during debugfull builds." FORCE)
mark_as_advanced(CMAKE_CXX_FLAGS_DEBUGFULL CMAKE_C_FLAGS_DEBUGFULL)
# Update the documentation string of CMAKE_BUILD_TYPE for ccache & cmake-gui
set(CMAKE_BUILD_TYPE "${CMAKE_BUILD_TYPE}" CACHE STRING
"Choose the type of build, options are: None debugfull Debug Release RelWithDebInfo MinSizeRel."
FORCE)
# coverage support
if(CMAKE_COMPILE_GCOV)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage")
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lprofile_rt" CACHE STRING "Flags used by the linker" FORCE)
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -lprofile_rt" CACHE STRING "Flags used by the linker" FORCE)
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -lprofile_rt" CACHE STRING "Flags used by the linker" FORCE)
endif()
endif()
endif()
if(MSVC)
set(_ENABLE_EXCEPTIONS -EHsc)
endif()
add_definitions(-DQT_NO_CAST_FROM_ASCII -DQT_NO_CAST_TO_ASCII)
add_definitions(-DQT_NO_KEYWORDS)
add_definitions(-DQT_USE_FAST_CONCATENATION -DQT_USE_FAST_OPERATOR_PLUS)
############### Configure checks ###############
set(AKONADI_SYSTEM_LIBS)
find_package(Backtrace)
if(Backtrace_FOUND)
include_directories(${Backtrace_INCLUDE_DIRS})
set(AKONADI_SYSTEM_LIBS ${AKONADI_SYSTEM_LIBS} ${Backtrace_LIBRARIES})
endif()
check_include_files(unistd.h HAVE_UNISTD_H)
# set the output paths
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin)
if(WIN32)
set(LIBRARY_OUTPUT_PATH ${EXECUTABLE_OUTPUT_PATH})
else()
set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/lib)
endif()
# Set up RPATH handling, so the libs are found if they are installed to a non-standard location.
# By default cmake builds the targets with full RPATH to everything in the build directory,
# but then removes the RPATH when installing.
# These two options below make it set the RPATH of the installed targets to all
# RPATH directories outside the current CMAKE_BINARY_DIR and also the library
# install directory, but only if this directory is not a default system library directory. Alex
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
list(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${LIB_INSTALL_DIR}" _isSystemLibDir)
if("${_isSystemLibDir}" STREQUAL "-1")
set(CMAKE_INSTALL_RPATH "${LIB_INSTALL_DIR}")
endif()
if(NOT DEFINED AKONADI_BUNDLE_PATH)
set(AKONADI_BUNDLE_PATH "/Applications/KDE4")
endif()
if(APPLE)
message(STATUS "MacOS Bundle Path: ${AKONADI_BUNDLE_PATH}")
set(CMAKE_INSTALL_NAME_DIR ${LIB_INSTALL_DIR})
endif()
############### Generate files ###############
# Used in configure_file() and install(EXPORT). Must be set before setting the AkonadiConfig.cmake vars.
set(AKONADI_TARGET_PREFIX Akonadi__)
if(Soprano_FOUND)
set(HAVE_SOPRANO TRUE)
endif()
configure_file(akonadi-prefix.h.cmake ${Akonadi_BINARY_DIR}/akonadi-prefix.h)
configure_file(config-akonadi.h.cmake ${Akonadi_BINARY_DIR}/config-akonadi.h)
# This command will replace the installation dirs with absolute paths in AkonadiConfig.cmake
configure_package_config_file(AkonadiConfig.cmake.in ${Akonadi_BINARY_DIR}/AkonadiConfig.cmake
INSTALL_DESTINATION ${LIB_INSTALL_DIR}/cmake/Akonadi
PATH_VARS BIN_INSTALL_DIR INCLUDE_INSTALL_DIR
LIB_INSTALL_DIR CONFIG_INSTALL_DIR
DBUS_INTERFACES_INSTALL_DIR DBUS_SERVICES_INSTALL_DIR
SHARE_INSTALL_PREFIX XDG_MIME_INSTALL_DIR
)
# this file is used by to check if the installed version can be used.
write_basic_package_version_file(${Akonadi_BINARY_DIR}/AkonadiConfigVersion.cmake
VERSION ${AKONADI_VERSION}
COMPATIBILITY SameMajorVersion
)
if(NOT WIN32)
configure_file(${Akonadi_SOURCE_DIR}/akonadi.pc.cmake ${Akonadi_BINARY_DIR}/akonadi.pc @ONLY)
endif()
############### build targets ###############
include_directories(${Akonadi_SOURCE_DIR} ${Akonadi_BINARY_DIR} ${QT_INCLUDES} ${Boost_INCLUDE_DIR})
add_subdirectory(interfaces)
add_subdirectory(libs)
set(AKONADI_PROTOCOLINTERNALS_LIBS ${akonadiprotocolinternals_LIB_DEPENDS} akonadiprotocolinternals)
add_subdirectory(shared)
add_subdirectory(agentserver)
add_subdirectory(server)
add_subdirectory(rds)
if(NOT WIN32)
add_subdirectory(asapcat)
endif()
if (NOT QT5_BUILD)
if(SQLITE_FOUND)
option(SQLITE_LINK_STATIC "link libsqlite3 statically" FALSE)
add_subdirectory(qsqlite)
endif()
endif()
############### install stuff ###############
install(FILES ${Akonadi_BINARY_DIR}/AkonadiConfigVersion.cmake
${Akonadi_BINARY_DIR}/AkonadiConfig.cmake
DESTINATION ${LIB_INSTALL_DIR}/cmake/Akonadi)
install(FILES akonadi-mime.xml DESTINATION ${XDG_MIME_INSTALL_DIR})
update_xdg_mimetypes(${XDG_MIME_INSTALL_DIR})
if(NOT WIN32)
install(FILES ${Akonadi_BINARY_DIR}/akonadi.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
endif()
feature_summary(WHAT ALL
INCLUDE_QUIET_PACKAGES
FATAL_ON_MISSING_REQUIRED_PACKAGES
)
# Install the file with the exported targets
install(EXPORT akonadiLibraryTargets
NAMESPACE ${AKONADI_TARGET_PREFIX}
DESTINATION ${LIB_INSTALL_DIR}/cmake/Akonadi
FILE AkonadiTargetsWithPrefix.cmake)

13
akonadi/CTestConfig.cmake Normal file
View file

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

22
akonadi/CTestCustom.cmake Normal file
View file

@ -0,0 +1,22 @@
# This file contains all the specific settings that will be used
# when running 'make Experimental'
# Change the maximum warnings that will be displayed
# on the report page (default 50)
set(CTEST_CUSTOM_MAXIMUM_NUMBER_OF_WARNINGS 1000)
# Errors that will be ignored
set(CTEST_CUSTOM_ERROR_EXCEPTION
${CTEST_CUSTOM_ERROR_EXCEPTION}
"ICECC"
"Segmentation fault"
"GConf Error"
"Client failed to connect to the D-BUS daemon"
"Failed to connect to socket"
"qlist.h.*increases required alignment of target type"
"qmap.h.*increases required alignment of target type"
"qhash.h.*increases required alignment of target type"
)
# No coverage for these files (auto-generated, unit tests, etc)
set(CTEST_CUSTOM_COVERAGE_EXCLUDE ".moc$" "moc_" "ui_" "/libs/tests" "/server/tests" "qrc_" "adaptor.h$" "adaptor.cpp$" "/server/[^/]+interface\\.")

8
akonadi/CodingStyle.txt Normal file
View file

@ -0,0 +1,8 @@
The all directory "akonadi" is tested for all rules of the coding style.
But of the qsqlite subdirectory which contains a .no_coding_style file.
The rules and all the scripts are free for download and comments at:
http://techbase.kde.org/Policies/Kdepim_Coding_Style
Feel free to communicate any comments or/and bugs:
guy dot maurel at kde dot org

64
akonadi/INSTALL Normal file
View file

@ -0,0 +1,64 @@
Akonadi's build system uses cmake.
So to compile Akonadi first create a build dir
mkdir build
cd build
then run cmake:
cmake ..
(a typical cmake option that is often used is: -DCMAKE_INSTALL_PREFIX=<prefix>)
cmake then presents a configuration summary. At this point you may
want to install missing dependancies (if you do, remove the CMakeCache.txt)
and run cmake again.
Finally build Akonadi:
make
And install it (in most cases root privileges are required):
make install
That's all :)
=== Build Options ===
The following options are available when running CMake:
* AKONADI_BUILD_TESTS (Default: TRUE): Build the Akonadi unit tests
* AKONADI_BUILD_QSQLITE (Default: TRUE): Build the SQLite backend
* INSTALL_QSQLITE_IN_QT_PREFIX (Default: FALSE): Useful for distributions.
Once enabled, the qsqlite3 backend will be installed in ${QT_PLUGINS_DIR}/sqldrivers
* STATIC_LIBRARY (Default: FALSE): Build the Akonadi server libraries statically. Only useful for certain cases (eg: WINCE builds).
* DATABASE_BACKEND (Default: MYSQL, available: MYSQL, POSTGRES, SQLITE): Define which database driver to use by default.
MYSQL is preferred, SQLITE should be avoided.
* QT5_BUILD (Default: FALSE): Build against Qt5 instead of Qt4.
* WITH_SOPRANO (Default: TRUE): Don't build with Soprano/Nepomuk support
=== Build Requirements ===
Required:
* Boost (http://www.boost.org)
* CMake (http://www.cmake.org) >= 2.8.8
* Qt4 >= 4.6.0 (http://qt.nokia.com/downloads)
* Shared-mime-info >= 0.20 (http://freedesktop.org/wiki/Software/shared-mime-info)
* Xsltproc (http://xmlsoft.org/XSLT/downloads.html)
Optional:
* Mysqld (http://www.mysql.com) - Optional at build time. You can pass -DMYSQLD_EXECUTABLE=/path/to/mysqld when running CMake instead
* SQlite >= 3.6.23 (http://www.sqlite.org) - Needed if you want to build the Sqlite backend
* Postgresql (http://www.postgres.org) - Optional at build time. You can pass -DPOSTGRES_PATH=/path/to/pg_ctl when running CMake instead
* Soprano (http://soprano.sourceforge.net)
=== Runtime Requirements ===
* SQlite if you plan to use the SQLite backend (NOT RECOMMENDED for desktop)
* MySQL server >= 5.1.3 (or compatible replacements such as MariaDB) if you plan to use the Mysql backend
* a Postgresql server if you plan to use the Postgres backend

View file

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>${MACOSX_BUNDLE_EXECUTABLE_NAME}</string>
<key>CFBundleGetInfoString</key>
<string>${MACOSX_BUNDLE_INFO_STRING}</string>
<key>CFBundleIconFile</key>
<string>${MACOSX_BUNDLE_ICON_FILE}</string>
<key>CFBundleIdentifier</key>
<string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleLongVersionString</key>
<string>${MACOSX_BUNDLE_LONG_VERSION_STRING}</string>
<key>CFBundleName</key>
<string>${MACOSX_BUNDLE_BUNDLE_NAME}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string>
<key>CFBundleVersion</key>
<string>${MACOSX_BUNDLE_BUNDLE_VERSION}</string>
<key>CSResourcesFileMapped</key>
<true/>
<key>LSRequiresCarbon</key>
<true/>
<key>LSUIElement</key>
<string>1</string>
<key>NSHumanReadableCopyright</key>
<string>${MACOSX_BUNDLE_COPYRIGHT}</string>
</dict>
</plist>

340
akonadi/Mainpage.dox Normal file
View file

@ -0,0 +1,340 @@
/**
\mainpage %Akonadi Server
<p><b>
Overview |
\ref akonadi_server_definitions |
\ref akonadi_server_srclayout
</b></p>
Akonadi aims to be an extensible cross-desktop storage service for PIM data
and meta data providing concurrent read, write, and query access.
It provides unique desktop-wide object identification and retrieval.
This is the API documentation for the Akonadi server. If you are using Akonadi
from within KDE, you almost certainly want the
<a href="http://api.kde.org/4.x-api/kdepimlibs-apidocs/akonadi/html/index.html">KDE client library documentation</a>.
This API reference is more useful to people implementing client libraries or
working on the Akonadi server itself.
For additional information, see the <a href="http://community.kde.org/KDE_PIM/Akonadi">Akonadi website</a>.
\section akonadi_server_architecture Architecture
<img src="http://community.kde.org/images.community/8/8e/Akonadi_Architecture.png"/>
The Akonadi framework uses a client/server architecture. The Akonadi server has the following primary tasks:
\li Abstract access to data from arbitrary sources, using toolkit-agnostic protocols and data formats
\li Provide a data cache shared among several clients
\li Provide change notifications and conflict detection
\li Support offline change recording and change replay for remote data
\subsection akonadi_server_design_principles Design Principles
The Akonadi architecture is based on the following four design principles:
\li <em>Functionality is spread over different processes.</em><br>
This separation has the big advantage that if one process crashes because of
a programming error it doesn't affect the other components. That results in
robustness of the whole system. A disadvantage might be that there is an additional
overhead due to inter-process communication.
\li <em>Communication protocol is split into data and control channel.</em><br>
When doing communication between processes you have to differentiate between the type of data
that is being transferred. For a large amount of data a high-performance
protocol should be used and for control data a low-latency protocol.
Matching both requirements in one protocol is mostly impossible and hard to
achieve with currently available software.
\li <em>Separate logic from storage.</em><br>
By separating the logic from the storage, the storage can be used to store data
of any type. In this case, the storage is a kind of service, which is available for
other components of the system. The logic is located in separated components and so
3rd-party developers can extend the system by providing their own components.
\li <em>Keep communication asynchronous.</em><br>
To allow a non-blocking GUI, all the communication with the back-end and within the
back-end itself must be asynchronous. You can easily provide a synchronous convenience
for the application developer; the back-end, however, must communicate asynchronously.
\subsection akonadi_server_components Components
The Akonadi server itself consists of a number of components:
\li The Akonadi control process (\c akonadi_control). It is responsible for managing all other server components
and Akonadi agents.
\li The Akonadi server process (\c akonadiserver). The actual data access and caching server.
\li The Akonadi agent server (\c akonadi_agent_server). Allows running of multiple Akonadi agents in one process.
\li The Akonadi agent launcher (\c akonadi_agent_launcher). A helper process for running Akonadi agents.
\li The Akonadi control tool (\c akonadictl). A tool to start/stop/restart the Akonadi server system and query its status.
This is the only program of these listed here you should ever run manually.
\li The Akonadi protocol library (\c libakonadiprotocolinternals), Contains protocol definitions and protocol parsing methods
useful for client implementations.
\subsubsection akonadi_server_components_server The Akonadi server process
The %Akonadi server process (\c akonadiserver) has the following tasks:
\li Provide a transaction-safe data store.
\li Provide operations to add/modify/delete items and collections in the local store, implementing the server side of the ASAP protocol.
\li Cache management of cached remote contents.
\li Manage virtual collections representing search results.
\li Provide change notifications for all known Akonadi objects over D-Bus.
\subsubsection akonadi_server_components_control The Akonadi server control process
The %Akondi control process (\c akonadi_control) has the following tasks:
\li Manage and monitor the other server processes.
\li Lifecycle management of agent instances using the various supported agent launch methods.
\li Monitor agent instances and provide crash recovery.
\li Provide D-Bus API to manage agents.
\li Provide change notifications on agent types and agent instances.
\section akonadi_server_objects Objects and Data Types
The %Akonadi server operates on two basic object types, called items and collections. They are comparable to files and directories
and are described in more detail in this section.
\subsection akonadi_server_objects_items Akonadi Items
An item is a generic container for whatever you want to store in Akonadi (eg. mails,
events, contacts, etc.). An item consists of some generic information (such as identifier,
mimetype, change date, flags, etc.) and a set of data fields, the item parts. Items
are independent of the type of stored data, the semantics of the actual content is only
known on the client side.
\subsubsection akonadi_server_objects_items_parts Item Parts
%Akonadi items can have one or more parts, e.g. an email message consists of the
envelope, the body and possible one or more attachments. Item parts are identified
by an identifier string. There are a few special pre-defined part identifiers (ALL,
ENVELOPE, etc.), but in general the part identifiers are defined by the type specific
extensions (ie. resource, serializer plugin, type specific client library).
\subsubsection akonadi_server_objects_items_attributes Item Tags
%Tags are self-contained entities stored in separate database table. A tag is a
relation between multiple items. Tags can have different types (PLAIN, ...) and applications
can define their own type to describe application-specific relations. Tags can also have
attributes to store additional metadata about the relation the tag describes.
\subsubsection akonadi_server_objects_items_serializer Payload Data Serialization
Item payload data is typically serialized in a standard format to ensure interoperability between different
client library implementations. However, the %Akonadi server does not enforce any format,
payload data is handled as an opaque binary blob.
\subsection akonadi_server_objects_collections Collections
Collections are sets of items. Every item is stored in exactly one
collection, this is sometimes also referred to as the "physical" storage location of the item.
An item might also be visible in several other collections - so called "virtual collections" -
which are defined as the result set of a search query.
Collections are organized hierarchically, i.e. a collection can have child
collections, thus defining a collection tree.
Collections are uniquely identified by their identifier in
contrast to their path, which is more robust with regard to renaming and moving.
\subsubsection akonadi_server_objects_collections_akonadi Collection Properties
Every collection has a set of supported content types.
These are the mimetypes of items the collection can contain.
Example: A collection of a folder-less iCal file resource would only support
"text/calendar" items, a folder on an IMAP server "message/rfc822" but also
"inode/directory" if it can contain sub-folders.
There is a cache policy associated with every collection which defines how much
of its content should be kept in the local cache and for how long.
Additionally, collections can contain an arbitrary set of attributes to represent
various other collection properties such as ACLs, quotas or backend-specific data
used for incremental synchronization. Evaluation of such attributes is the responsibility
of client implementations, the %Akonadi server does not interpret properties
other than content types and cache policies.
\subsubsection akonadi_server_objects_collections_tree Collection Tree
There is a single collection tree in Akonadi, consisting of several parts:
- A root node, id 0
- One or more top-level collections for each resource. Think of these as mount-points
for the resource. The resources must put their items and sub-collections into their
corresponding top-level collection.
- Resource-dependent sub-collections below the resource top-level collections.
If the resource represents data that is organized in folders (e.g. an IMAP
resource), it can create additional collections below its top-level
collection. These have to be synched with the corresponding backend by the
resource.
Resources which represent folder-less data (e.g. an iCal file) don't need
any sub-collections and put their items directly into the top-level collection.
- A top-level collection containing virtual collections.
Example:
\verbatim
+-+ resource-folder1
| +- sub-folder1
| +- sub-folder2
| ...
+-+ resource-folder2
| ...
|
+-+ Searches
+- search-folder1
+- search-folder2
...
\endverbatim
\subsection akonadi_server_objects_identification Object Identification
\subsubsection akonadi_server_objects_identification_uid Unique Identifier
Every object stored in %Akonadi (collections and items) has a unique
identifier in the form of an integer value. This identifier cannot be changed in
any way and will stay the same, regardless of any modifications to the referred
object. A unique identifier will never be used twice and is globally unique,
therefore it is possible to retrieve an item without knowing the collection it belongs to.
\subsubsection akonadi_server_objects_identification_rid Remote Identifier
Every object can also have an optional so-called remote identifier. This is an
identifier used by the corresponding resource to identify the object on its
backend (e.g., a groupware server).
The remote identifier can be changed by the owning resource agent only.
Special case applies for Tags, where each tag can have multiple remote IDs. This fact is
however opaque to resources as each resource is shown only the remote ID that it had
provided when inserting the tag into Akonadi.
\subsubsection akonadi_server_objects_identification_gid Global Identifier
Every item can has also so called GID, an identifier specific to the content (payload)
of the item. The GID is extracted from the payload by client serializer when storing the
item in Akonadi. For example, contacts have vCard "UID" field as their GID, emails can
use value of "Message-Id" header.
\section akonadi_server_protocols Communication Protocols
For communication within the Akonadi server infrastructure and for communication with Akonadi clients, two communication technologies are used:
\li \em D-Bus Used for management tasks and change notifications.
\li \em ASAP (Akonadi Server Access Protocol), used for high-throughput data transfer. ASAP is based on the well-known IMAP protocol (RFC 3501)
which has been proven it's ability to handle large quantities of data in practice already.
\todo add protocol documentation
\section akonadi_server_interaction Interacting with Akonadi
There are various possibilities to interact with %Akonadi.
\section akonadi_server_interaction_client_libraray Akonadi Client Libraries
Accessing the %Akonadi server using the ASAP and D-Bus interfaces directly is cumbersome.
Therefore you'd usually use a client library implementing the low-level protocol handling
and providing convenient high-level APIs for %Akonadi operations.
Currently, the most complete implementation is the
<a href="http://api.kde.org/4.x-api/kdepimlibs-apidocs/akonadi/html/index.html">KDE %Akonadi client library</a>.
<!--
// Afaik there are no "other ones"? -- dvratil
\todo add links to the other ones
//-->
\subsection akonadi_server_interaction_agents Akonadi Agents
%Akonadi agents are processes which are controlled by the Akonadi server itself. Agents typically
operate autonomously (ie. without much user interaction) on the objects handled by Akonadi, mostly
by reacting to change notifications sent by the %Akonadi server.
Agents can implement specialized interfaces to provide additional functionality.
The most important ones are the so-called resource agents.
Resource agents are connectors that provide access to data from an external source, and replay local changes
back to their corresponding backend.
\section akonadi_server_implementation Implementation Details
\subsection akonadi_server_implementation_storage Data and Metadata Storage
The Akonadi server uses two mechanisms for data storage:
\li A SQL databases for metadata and small payload data
\li Plain files for large payload data
More details on the SQL database layout can be found here: \ref akonadi_server_database.
The following SQL databases are supported by the Akonadi server:
\li \em MySQL using the default QtSQL driver shipped with Qt
\li \em Sqlite using the improved QtSQL driver shipped with the Akonadi server
\li \em PostgreSQL using the default QtSQL driver shipped with Qt
For details on how to configure the various backends, see Akonadi::DataStore.
\page akonadi_server_definitions Type Definitions
<p><b>
\ref index "Overview" |
\ref Type Definitions |
\ref akonadi_server_srclayout
</b></p>
To let all components play together nicely, we have to use some common encoding
definitions.
\li <em>Collection names</em><br>
Collection names and paths are Unicode strings (QString) to allow custom names by the user.
\li <em>Data references</em><br>
The persistent identifier is an unsigned integer and the external URL is
a Unicode string (QString).
\li <em>Transferred data over ASAP</em><br/>
The data transferred over ASAP are byte arrays (QByteArray). If Unicode strings are
transferred over ASAP, UTF-8 encoding is applied.
\li <em>Error and status messages</em><br>
Error and status messages are visible to the user, so they have to be
Unicode strings (QString).
\page akonadi_server_srclayout Source Code Layout
<p><b>
\ref index "Overview" |
\ref akonadi_server_definitions |
\ref Source Code Layout
</b></p>
The code of the storage and control components is located in the \c server sub-directory.
The different parts are laid out as follows:
<ul>
<li> \e control <br>
Contains the source code of the \ref akonadi_design_control "control" component.
<li> \e interfaces <br>
Contains the D-Bus interface descriptions of the Akonadi components
<li> \e src <br>
Contains the source code of the \ref akonadi_design_storage "storage" component.
<li> \e src/handler <br>
Contains the source code for the handlers of the single ASAP commands.
See <a href="group__akonadi__server__handler.html">command handlers module</a>
<li> \e src/storage <br>
Contains the source code for accessing the storage back-end.<br>
<ul>
<li> entity.{h,cpp} <br>
The files contain classes which reflect records in the tables of the database.
They are generated by XSL transformation from akonadidb.xml and entities.xsl
<li> datastore.{h,cpp} <br>
The files contain a class which provides the access to the underlaying database tables.
</ul>
</ul>
*/
// DOXYGEN_EXCLUDE = sqlplugin server/control server/akonadictl server/tests
// DOXYGEN_PROJECTNAME=Akonadi
// DOXYGEN_PROJECTVERSION=1.10.43
// vim:ts=4:sw=4:expandtab:filetype=doxygen

529
akonadi/NEWS Normal file
View file

@ -0,0 +1,529 @@
1.13.0 10-August-2014
----------------------------------------------
- Fixed virtual collections statistics
- Fixed tag RID fetch
- Fixed HRID-based fetches
- Fixed race condition in StorageDebugger
- Use FindBacktrace.cmake from CMake 3.0 instead of our own detection
1.12.90 07-July-2014
----------------------------------------------
- MERGE command for faster synchronization
- Optimizations in various commands handlers
- SELECT command is obsolete now
- Performance and concurrency improvements in QSQLITE3 driver
- Introduced Collection sync preferences as an improvement over the IMAP-based subscription model
- Disable filesystem copy-on-write for DB files when running on Btrfs
- Introduced direct streaming of external parts
- Fixed SearchManager DBus interface not being registered to DBus
- Fixed handling of tags in AK-APPEND and MERGE commands
- Various fixes in virtual collections handling
1.12.1 07-April-2014
----------------------------------------------
- Fixed deadlock in SearchManager
- Fixed notification emission when appending items
- Fixed ItemRetriever ignoring changeSince argument
- Fixed X-AKAPPEND command response
- Fixed RID-based FETCH
- Fixed data loss in case of long-lasting copy or move operations
1.12.0 25-March-2014
----------------------------------------------
- Improved 'akonadictl status' command output
- Fixed indexing of items in collections with short cache expiration
- Fixed building Akonadi in subdirectory
- Fixed deadlock in SearchManager
- Fixed runtime warnings
1.11.90 19-March-2014
----------------------------------------------
- Fixed collection scheduling
- Fixed indexing of expired items from local resources
- Fixed database schema update with PostgreSQL
- Fixes in searching and search updates
1.11.80 28-February-2014
----------------------------------------------
- Server-search support
- Search plugins support
- Tags support
- Fixes and improvements in search
- Fixes in protocol parser
- Fixed inter-resource moves
- Fixed .desktop files parsing
- Optimized collections tasks scheduling
- Optimized flags handling
- Optimized appending new items via AK-APPEND
- Handle database transactions deadlocks and timeouts
- Improved PostgreSQL support
- Soprano is now an optional dependency
- Removed MySQL Embedded support
1.11.0 28-November-2013
----------------------------------------------
- fix joined UPDATE queries failing with SQLite
1.10.80 05-November-2013
----------------------------------------------
- Servser-side notification filtering
- GID support
- Export custom agent properties to clients
- Faster Akonadi shutdown
- Improved and faster database schema check on start
- Enabled C++11 support
- Optimize some SQL queries
- Store only relative paths to external payload files in database
1.10.3 04-October-2013
----------------------------------------------
- Fix support for latest PostgreSQL
- Check MySQL version at runtime, require at least 5.1
- Fix crash when destroying DataStore with backends other than MySQL
- Fix problem with too long socket paths
- Send dummy queries to MySQL to keep the connection alive
- Fix crash when no flags are changed
1.10.2 23-July-2013
----------------------------------------------
- Fix PostgreSQL support (once more)
1.10.1 22-July-2013
----------------------------------------------
- Fix PostgreSQL support
- Optimize appending flags to items
- Introduce CHANGEDSINCE parameter to FETCH command
1.10.0 09-July-2013
----------------------------------------------
- Memory optimizations
- Fix a runtime error on Windows
1.9.80 10-June-2013
----------------------------------------------
- Update item access time less often.
- Don't try to start akonadiserver if mysqld is not installed
- Allow to fetch available items even if there are errors in some of the items.
- Properly restrict the external part removal to the deleted collection.
- Support checking the cache for payloads in the FETCH command.
- Add infrastructure to track client capabilities.
- Allow to disable the cache verification on retrieval.
- fsck: move orphaned pim items to lost+found, delete orphaned pim item flags.
- Introduce NotificationMessageV2 that supports batch operations on set of entities.
- Fix build with Boost >= 1.53.
- Fix a runtime issue with MySQL >= 5.6 (MySQL >= 5.1.3 is now the minimum version).
1.9.2 05-May-2013
---------------------------------------------
- Add option to FETCH to ignore external retrieval failures.
- Properly restrict external payload removal.
- Add buildsystem option to choose between Qt4 and Qt5.
1.9.1 02-March-2013
---------------------------------------------
- Disable query cache for Sqlite.
- Handle missing mysqld better.
- Ignore my.cnf settings when using the internal MySQL server.
1.9.0 23-December-2012
---------------------------------------------
- Respect collection cache policy refresh interval for collection tree sync.
- Fix initialization of PostgreSQL database.
- Correctly count items flags in virtual collections.
- Notify parent virtual collections about item changes.
- Require CMake >= 2.8.8.
- Remove dependency to Automoc4.
- Support Qt 5.
1.8.80 12-November-2012
---------------------------------------------
- Recover from lost external payload files.
- Improve the virtual collections handling.
- Notify clients about database schema updates.
- Reduce item access time updates.
- Make use of referential integrity if supported by the database backend.
- Add prepared query cache.
- Many code and queries optimizations.
1.8.1 14-October-2012
---------------------------------------------
- Fix payload loss on some move/copy scenarios.
- Improve error reporting for failed item retrievals.
1.8.0 25-July-2012
---------------------------------------------
- Fix deadlock in ad-hoc Nepomuk searches.
1.7.95 11-July-2012
---------------------------------------------
- Fix Nepomuk queries getting stuck if Nepomuk service crashes.
- Fix unecessary remote retrieval of already cached item parts.
- Reset RID/RREV during cross-resource collection moves.
- Increase timeout for remote item retrieval.
1.7.90 08-June-2012
---------------------------------------------
- Fix handling of large SPARQL queries.
- Support cleanup of orphaned resources in the consistency checker.
- Support compilation with Clang.
1.7.2 31-March-2012
---------------------------------------------
- Fix and optimize searching via Nepomuk.
1.7.1 03-March-2012
---------------------------------------------
- Don't truncate SPARQL queries in virtual collections.
- Optimize change notifications for deleted collection attributes.
- Fix possible data loss during item copy/move operations.
1.7.0 23-January-2012
---------------------------------------------
- Fix search result retrieval from Nepomuk.
1.6.90 20-December-2011
---------------------------------------------
- Support for PostgreSQL >= 9.
- Improve RFC 3501 compatibility in LOGIN and non-silent SELECT commands.
- Add support for running multiple instance concurrently in the same user session.
- Update agent interface to include collectionTreeSynchronized signal.
- Add consistency checker system.
- Add support for database vacuuming.
- Various optimizations to reduce the number of SQL queries.
1.6.2 03-October-2011
---------------------------------------------
- Do not update item revision if only the RID or RREV changed.
- Fix usage of wrong ids for part filenames.
- Only set item dirty flag if the payload changed.
- Only drop content mimetype for unsubscribed collections in LIST/LSUB.
1.6.1 15-September-2011
---------------------------------------------
- Fix crash on agent launcher exit.
- Fix valgrind-ing agents running in the agent launcher.
- Fix restarting of agents in broken state.
- Fix pipe naming on multi-user Windows systems.
- Raise MySQL timeout.
1.6.0 10-July-2011
---------------------------------------------
- Enable external payload storage unconditionally.
- Treat single UID/RID fetches as error if the result set is empty.
1.5.80 21-May-2011
---------------------------------------------
- WinCE database performance improvements.
- Include destination resource in move notifications.
- Fix crash in protocol parser.
- Fix possible race on accessing table caches.
- Use QStringBuilder if available.
- Improved notification message API.
1.5.3 07-May-2011
---------------------------------------------
- Fix crash when copying collections into themselves.
1.5.2 05-April-2011
---------------------------------------------
- Fix XdgBaseDirs reporting duplicated paths.
- Use correct database name when using internal MySQL.
1.5.1 28-February-2011
---------------------------------------------
- Unbreak searching with Nepomuk 4.6.
1.5.0 22-January-2011
---------------------------------------------
- Fix Boost related build issues on Windows.
- Hide akonadi_agent_launcher from Mac OS X dock.
1.4.95 07-January-2011
---------------------------------------------
- Optimize notification compression.
- Consider ignore flag when calculating collection statistics.
- Fix item payload size calculation.
- Improved FETCH response order heuristic.
- Fix Strigi-based persistent search folders.
- Fix error propagation in FETCH command handler.
1.4.90 20-December-2010
---------------------------------------------
- Set agent status for crashed instances.
- Allow to restart crashed agent instances.
- Automatically recover from loss of the resource table.
- Allow to specify the query language in persistent search commands.
- Fix leak of notification sources.
1.4.85 18-December-2010
---------------------------------------------
- Fix agent server startup race.
- Allow to globally enable/disable the agent server.
- Fix autostart of agents running in the agent server.
- Fix agent configuration when running in the agent server.
- Fix agent server shutdown crash.
- Put sockets into /tmp to support AFS/NFS home directories.
- Fix access rights on persistent search folders.
- Add support for sub-collection tree syncs in resource interface.
1.4.80 21-November-2010
---------------------------------------------
- Experimental support for MeeGo.
- Return changed revision numbers in STORE response.
- Fix Nepomuk searches mixing up items and email attachments.
- Experimental Strigi search backend.
- Compensate for Nepomuk D-Bus API breakage.
- Fix parsing of serialization format version.
- Optimize collection statistics queries.
- Optimize protocol output generation.
- Optimize protocol parsing.
- Build-time configurable default database backend.
- Fix ancestor chain quoting.
- Fix finding of components on Windows in install location.
- New subscription interface for change notifications.
- Support for in-process agents and agent server.
- Support for Sqlite.
- Experimental support for ODBC-based database backends.
- Support Windows CE.
1.4.1 22-October-2010
---------------------------------------------
- Improve range query performance.
- Fix MySQL database upgrade happening too early.
- Fix MySQL database upgrade setting wrong priviledges.
- Fix non-index access slowing down server startup.
- ASAP parser performance optimizations
- Respect SocketDirectory setting also for database sockets.
- Allow $USER placeholder in SocketDirectory setting.
- Fix ASAP parser failing on non-zero serialization format versions.
1.4.0 31-July-2010
---------------------------------------------
- Add change notification for collection subscription state changes.
- Enable filesystem payload store by default.
- Fix unicode folder name encoding regression.
1.3.90 04-July-2010
---------------------------------------------
- Reset RIDs on inter-resource moves.
- Optimize disk space usage with internal MySQL.
- Improve error reporting of the Akonadi remote debugging server.
- Fix moving collections into the collection root.
- Report PostgreSQL database errors in english independent of locale settings.
- Fix unicode collection name encoding.
- Optimize cache pruning with filesystem payload store.
- Fix automatic migration between database and filesystem payload store.
1.3.85 09-June-2010
---------------------------------------------
- Avoid unneeded full resource sync when using sync-on-demand cache policies.
- Fix crash when using D-Bus session bus in a secondary thread.
- Reduce emission of unneccessary change notifications.
- Fix empty filename use in fs backend.
1.3.80 27-May-2010
---------------------------------------------
- Fix unicode collection name encoding.
- Support HRID-based FETCH commands.
- Fix Nepomuk-based persistent searches when Nepomuk was not running during Akonadi startup.
- Fix compilation on Windows CE.
- Optimize item retrieval queries.
- Support modification of existing persistent searches.
- Support different query languages for persistent searches.
- Fix PostgreSQL shutdown.
- Add initial support for Sqlite.
- Fix premature command abortion.
- Fix parsing of cascaded lists.
- Support for mysql_update_db.
- Support for mysql_install_db.
- Improved protocol tracing for akonadiconsole.
- Support MySQL backend on Maemo.
- Allow RID changes only to the owning resource.
- Add Akonadi remote debugging server.
- Add support for marking chaced payloads as invalid.
- Add support for remove revision property.
- Fix MySQL connection loss after 8 hours of inactivity.
- Fix D-Bus race on server startup.
- Fix internal MySQL on Windows.
- Fix config and data file location on Windows.
- Fix PostgreSQL startup when using internal server.
- Refactor database configuration abstraction.
1.3.1 09-February-2010
---------------------------------------------
- Fix D-Bus connection leak in Nepomuk search backend.
- Disable slow query logging by default for internal MySQL.
1.3.0 20-January-2010
---------------------------------------------
- Work around D-Bus bug that could cause SEARCH to hang.
1.2.90 06-January-2010
---------------------------------------------
- Fix change notifications for search results.
- Fix database creation with PostgreSQL.
- Fix copying of item flags.
- Fix internal MySQL shutdown.
- Support PostgreSQL in internal mode.
- Fix table name case mismatch.
1.2.80 01-December-2009
---------------------------------------------
- Support for collection content type filtering as part of LIST.
- Adapt to Nepomuk query service changes.
- Experimental support for PostgreSQL.
- Support for preprocessor agents.
- Support for distributed searching.
- Support for agents creating virtual collections.
- Protocol parser fixes for non-Linux/non-KDE clients.
- Support for single-shot searches using the Nepomuk query service.
- Support HRID-based LIST operations.
- Support RID-based MOVE, COLMOVE, LINK and UNLINK opertions.
- Respect cache-only retrieval also regarding on-demand syncing.
- Add configuration accepted/rejected signals to the agent interface.
- Fix change notification compression when using modified parts sets.
- Use one retrieval pipeline per resource.
- Reduce unecessary change notification on flag changes.
- Fix RID quoting.
- Fix resource creating race for autostarted agents.
- Create new database also when using external db servers.
- Return the created result collection when creating a persistent search.
1.2.1 28-August-2009
---------------------------------------------
- Fix item creation with RID's containing a ']'.
- Fix ASAP parser not reading the entire command.
1.2.0 28-June-2009
---------------------------------------------
- Fix attribute joining in collection list results.
- Buildsystem fixes for Mac OS.
- Do not show a console window for akonadi_control on Windows.
1.1.95 23-June-2009
---------------------------------------------
- Fix item size handling.
- Add support for retrieving collection statistics as part
of the AKLIST/AKLSUB commands.
- Add support for collection size statistics.
- Build fixes for Windows.
- Support RID-based operations for CREATE, MODIFY and DELETE.
- Avoid emitting unecessary change notifications when
modifying items or collections.
- Add COLMOVE command.
- Reduce number of database writes when modifying a collection.
- Fix parsing of attributes containing CR or LF characters.
1.1.90 03-June-2009
---------------------------------------------
- Return the storage location for items in FETCH responses
- Fix remode identifier encoding problems
- Fix infinite loop when parsing RID lists
- Fix parsing errors on stray newlines
- Support RID-based operations for STORE and MOVE
- Fix race on resource creation
- Provide modified item parts in change notifications
- Build system fixes
1.1.85 05-May-2009
---------------------------------------------
- Improved CMake scripts so it is possible to detect
the Akonadi version in projects that depend on it.
- Simplified the check for existance of tables.
- Add a dedicated item deletion command, to get rid of
the old STORE/EXPUNGE which was extremely inefficient.
- Some fixes to support sqlite in the future.
- Soprano is required now.
- Qt 4.5.0 is required now.
- Support for collection retrieval by remote identifier.
- Support for item retrieval based on the remote identifier.
- Less useless debug output.
- Fixed leak on socket error.
- Various smaller bug fixes, see ChangeLog for a list.
- Support for writing large payloads to a file.
- New Item retrieval code.
- Added a streaming IMAP parser, and ported code the use it.
- Add support for manually restarting an agent instance.
1.1.2 30-Apr-2009
---------------------------------------------
- Avoid DBUS lockups, reported at: https://bugs.kde.org/182198
- Update user mysql.conf only if global/local one's are newer
1.1.1 21-Jan-2009
---------------------------------------------
- Fix code that was not executed in a release build.
- Require CMake 2.6.0 which fixes boost detection.
- Don't try to restart an agent that has been deleted.
1.1.0 03-Jan-2009
---------------------------------------------
- Restart agents when their executable changed.
- Buildsystem fixes to find and link boost on all platforms.
- Improvements to the startup to prevent partial startup.
- Include revision number in the version string when building from SVN.
- Shut down when we lost the connection to the D-Bus session bus.
- add some basic handling of command line args.
- Add a D-Bus call to flush the notification queue.
- Automatically fix world-writeable mySQL config files.
- Fix for FreeBSD mysql path.
1.0.81 16-Dec-2008
---------------------------------------------
- Restore protocol backward compatibility with Akonadi 1.0.x servers.
- Build system fixes.
- Fix compiler warnings.
- Fall back to the default server path if the configured one points
to a non-existing file.
1.0.80 19-Nov-2008
---------------------------------------------
- Query agent status information asynchronously and answer all queries from
cached values, reduces the risk of an agents blocking the Akonadi server.
- Increase mysql limits to more realistical values.
- Don't mark all new items as recent.
- Changes so it can store the size of an item.
- Better error detection.
- Prevent translated month names in the protocol.
- Some build fixes.
- Handle multiline output correctly.
- Terminate the control process when the server process failed to start.
- Add the ability to debug or valgrind a resource right from the
beginning, similar to the way this can be done with KIO slaves.
- Fix fetching of linked items in arbitrary collections.
- Add notification support for item references in virtual collections.
- Add LINK/UNLINK commands to edit references to items in virtual collections.
- Add a way to notify agents that their configuration has been changed remotely.
- Make sure that all modification times are stored in UTC time zone.
- Unquoted date time with a lenght of 26 characters was not parsed properly.
- Add serverside timestamp support for items.
1.0.0 22-July-2008
---------------------------------------------
- First official stable release
- Bugfix: Unquoted date time with a lenght of
26 characters was not parsed properly.
- Add serverside timestamp support for items.
- Build system fixes (windows & automoc)
0.82.0 18-June-2008
---------------------------------------------
- Several build and installation fixes for windows and mac.
- Some improvements in the build system.
- Add item part namespaces.
- Implemented all the fetch modes advertised in ItemFetchScope.
- Notify already running clieants about all found types during startup.
0.81.0 10-May-2008
---------------------------------------------
- Fix bug where full part was not fetched when a partial part was available already.
- Collection parsing optimalisation.
- Optimization for quoted string parsing.
- Use org.freedesktop namespace, instead of org.kde for the dbus interfaces.
- Add support for version numbers for database and protocol.
- Fixed foreach misusage.
- Depend on external automoc package instead of a copy.
0.80.0 24-Apr-2008
---------------------------------------------
- Initial release

36
akonadi/README Normal file
View file

@ -0,0 +1,36 @@
Akonadi
========
What is Akonadi?
------------------
Akonadi is a PIM layer, which provides an asynchronous API to access all kind
of PIM data (e.g. mails, contacts, events, todos etc.).
It consists of several processes (generally called the Akonadi server) and a
library (called client library) which encapsulates the communication
between the client and the server.
This directory contains the sources of the Akonadi server and all the infrastructure
that is needed to build the client libraries and the application which want to make
use of Akonadi.
Structure
----------
* cmake/
Contains the cmake checks that are needed to build the server.
* interfaces/
Contains the dbus interface descriptions that are used by the
client library to control the Akonadi server or request status
information.
* libs/
Contains the sources of a private library which provides utils
that are used by both, the Akonadi server and the client library.
* server/
See INSTALL for installation instructions.

53
akonadi/README.sqlite Normal file
View file

@ -0,0 +1,53 @@
== PREFACE ==
The reason we have our own QtSql Sqlite driver here is because the one shipped
with Qt misses a bunch of multi-threading fixes crucial for Akonadi. Of course,
these changes should be pushed upstream eventually.
== INSTALL ==
When Sqlite is found, the custom driver will be build and installed in:
${CMAKE_INSTALL_PREFIX}/lib/plugins/sqldrivers or ${QT_PLUGINS_DIR}/sqldrivers
if you enable the INSTALL_QSQLITE_IN_QT_PREFIX option when running CMake.
The next thing you have to do is add that path (if it isn't already) to your
QT_PLUGIN_PATH environment variable.
Now you should be able to configure the QSQLITE3 driver in akonadiserverrc.
== PROBLEMS ==
One of the problematic code paths seems to be:
server/src/handler/fetch.cpp:161-201
In this part the code is iterating over the results of an still active SELECT
query and during this iteration it also tries to do INSERT/UPDATE queries. This
means that there is probably a SHARED lock for the reading and a PENDING lock
for the writing queries. For sqlite to be able to write to the db it needs an
EXCLUSIVE lock. A PENDING lock only gets inclusive when all SHARED locks are
gone.
A possible solution might be to store the results of the SELECT query into
memory, close the query and than start the inserts/updates.
== SQLITE INFO ==
From www.sqlite.org: (see qsqlite/src/qsql_sqlite.cpp:525-529)
Run-time selection of threading mode
If single-thread mode has not been selected at compile-time or start-time, then
individual database connections can be created as either multi-thread or
serialized. It is not possible to downgrade an individual database connection
to single-thread mode. Nor is it possible to escalate an individual database
connection if the compile-time or start-time mode is single-thread.
The threading mode for an individual database connection is determined by flags
given as the third argument to sqlite3_open_v2(). The SQLITE_OPEN_NOMUTEX flag
causes the database connection to be in the multi-thread mode and the
SQLITE_OPEN_FULLMUTEX flag causes the connection to be in serialized mode. If
neither flag is specified or if sqlite3_open() or sqlite3_open16() are used
instead of sqlite3_open_v2(), then the default mode determined by the
compile-time and start-time settings is used.

View file

@ -0,0 +1,55 @@
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${_ENABLE_EXCEPTIONS}")
# Agent server
set(akonadi_agent_server_srcs
agentpluginloader.cpp
agentserver.cpp
agentthread.cpp
main.cpp
)
add_executable(akonadi_agent_server ${akonadi_agent_server_srcs})
target_link_libraries(akonadi_agent_server
akonadi_shared
${QT_QTGUI_LIBRARIES}
${QT_QTDBUS_LIBRARY}
${AKONADI_SYSTEM_LIBS}
${AKONADI_PROTOCOLINTERNALS_LIBS}
)
target_link_libraries(akonadi_agent_server ${Boost_PROGRAM_OPTIONS_LIBRARY})
# Agent plugin launcher
set(akonadi_agent_launcher_SRCS
agentpluginloader.cpp
agentlauncher.cpp
)
add_executable(akonadi_agent_launcher MACOSX_BUNDLE ${akonadi_agent_launcher_SRCS})
target_link_libraries(akonadi_agent_launcher
akonadi_shared
${QT_QTGUI_LIBRARIES}
${AKONADI_SYSTEM_LIBS}
${AKONADI_PROTOCOLINTERNALS_LIBS}
${Boost_PROGRAM_OPTIONS_LIBRARY}
)
if(Q_WS_MAC)
set_target_properties(akonadi_agent_launcher PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/../Info.plist.template)
set_target_properties(akonadi_agent_launcher PROPERTIES MACOSX_BUNDLE_GUI_IDENTIFIER "org.kde.Akonadi.agentlauncher")
set_target_properties(akonadi_agent_launcher PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Akonadi Agent Launcher")
endif()
# Install both helper apps.
if(Q_WS_MAC)
install(TARGETS akonadi_agent_launcher
DESTINATION ${AKONADI_BUNDLE_PATH})
else()
install(TARGETS akonadi_agent_launcher
DESTINATION ${BIN_INSTALL_DIR})
endif()
install(TARGETS akonadi_agent_server
DESTINATION ${BIN_INSTALL_DIR})

3
akonadi/agentserver/TODO Normal file
View file

@ -0,0 +1,3 @@
* When the AgentServer process crashes and is restarted by ProcessControl,
somehow the agents/resources that where running must be restarted as
well.

View file

@ -0,0 +1,61 @@
/*
Copyright (c) 2010 Bertjan Broeksema <broeksema@kde.org>
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
*/
#include "agentpluginloader.h"
#include <QtCore/QDebug>
#include <QtCore/QStringList>
#include <QApplication>
int main( int argc, char *argv[] )
{
QApplication app( argc, argv );
app.setQuitOnLastWindowClosed( false );
if ( app.arguments().size() != 3 ) { // Expected usage: ./agent_launcher ${plugin_name} ${identifier}
qDebug() << "Invalid usage: expected: ./agent_launcher pluginName agentIdentifier";
return 1;
}
const QString agentPluginName = app.arguments().at( 1 );
const QString agentIdentifier = app.arguments().at( 2 );
AgentPluginLoader loader;
QPluginLoader *factory = loader.load( agentPluginName );
if ( factory == 0 ) {
return 1;
}
QObject *instance = 0;
const bool invokeSucceeded = QMetaObject::invokeMethod( factory->instance(),
"createInstance",
Qt::DirectConnection,
Q_RETURN_ARG( QObject*, instance ),
Q_ARG( QString, agentIdentifier ) );
if ( invokeSucceeded ) {
qDebug() << "Agent instance created in separate process.";
} else {
qDebug() << "Agent instance creation in separate process failed";
return 2;
}
const int rv = app.exec();
delete instance;
return rv;
}

View file

@ -0,0 +1,52 @@
/*
Copyright (c) 2010 Bertjan Broeksema <broeksema@kde.org>
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
*/
#include "agentpluginloader.h"
#include "libs/xdgbasedirs_p.h"
#include "shared/akdebug.h"
using namespace Akonadi;
AgentPluginLoader::~AgentPluginLoader()
{
qDeleteAll( m_pluginLoaders );
m_pluginLoaders.clear();
}
QPluginLoader *AgentPluginLoader::load( const QString &pluginName )
{
const QString pluginFile = XdgBaseDirs::findPluginFile( pluginName );
if ( pluginFile.isEmpty() ) {
akError() << Q_FUNC_INFO << "plugin file:" << pluginName << "not found!";
return 0;
}
if ( m_pluginLoaders.contains( pluginFile ) ) {
return m_pluginLoaders.value( pluginFile );
} else {
QPluginLoader *loader = new QPluginLoader( pluginFile );
if ( !loader->load() ) {
akError() << Q_FUNC_INFO << "Failed to load agent: " << loader->errorString();
delete loader;
return 0;
}
m_pluginLoaders.insert( pluginFile, loader );
return loader;
}
}

View file

@ -0,0 +1,46 @@
/*
Copyright (c) 2010 Bertjan Broeksema <broeksema@kde.org>
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
*/
#ifndef AGENTPLUGINLOADER_H
#define AGENTPLUGINLOADER_H
#include <QtCore/QHash>
#include <QtCore/QPluginLoader>
class AgentPluginLoader
{
public:
/**
Deletes all instantiated QPluginLoaders.
*/
~AgentPluginLoader();
/**
Returns the loader for plugins with @param pluginName. Callers must not
take ownership over the returned loader. Loaders will be unloaded and deleted
when the AgentPluginLoader goes out of scope/gets deleted.
@return the plugin for @param pluginName or 0 if the plugin is not found.
*/
QPluginLoader *load( const QString &pluginName );
private:
QHash<QString, QPluginLoader *> m_pluginLoaders;
};
#endif // AGENTPLUGINLOADER_H

View file

@ -0,0 +1,134 @@
/*
Copyright (c) 2010 Volker Krause <vkrause@kde.org>
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
*/
#include "agentserver.h"
#include "agentthread.h"
#include "libs/xdgbasedirs_p.h"
#include "libs/protocol_p.h"
#include "shared/akdebug.h"
#include <QtCore/QCoreApplication>
#include <QtCore/QDebug>
#include <QtCore/QPluginLoader>
#include <QtCore/QTimer>
#include <QtDBus/QDBusConnection>
using namespace Akonadi;
AgentServer::AgentServer( QObject *parent )
: QObject( parent )
, m_processingConfigureRequests( false )
, m_quiting( false )
{
QDBusConnection::sessionBus().registerObject( QLatin1String( AKONADI_DBUS_AGENTSERVER_PATH ),
this, QDBusConnection::ExportScriptableSlots );
}
AgentServer::~AgentServer()
{
qDebug() << Q_FUNC_INFO;
if ( !m_quiting ) {
quit();
}
}
void AgentServer::agentInstanceConfigure( const QString &identifier, qlonglong windowId )
{
m_configureQueue.enqueue( ConfigureInfo( identifier, windowId ) );
if ( !m_processingConfigureRequests ) { // Start processing the requests if needed.
QTimer::singleShot( 0, this, SLOT(processConfigureRequest()) );
}
}
bool AgentServer::started( const QString &identifier ) const
{
return m_agents.contains( identifier );
}
void AgentServer::startAgent( const QString &identifier, const QString &typeIdentifier, const QString &fileName )
{
akDebug() << Q_FUNC_INFO << identifier << typeIdentifier << fileName;
//First try to load it staticly
Q_FOREACH ( QObject *plugin, QPluginLoader::staticInstances() ) {
if ( plugin->objectName() == fileName ) {
AgentThread *thread = new AgentThread( identifier, plugin, this );
m_agents.insert( identifier, thread );
thread->start();
return;
}
}
QPluginLoader *loader = m_agentLoader.load( fileName );
if ( loader == 0 ) {
return; // No plugin found, debug output in AgentLoader.
}
Q_ASSERT( loader->isLoaded() );
AgentThread *thread = new AgentThread( identifier, loader->instance(), this );
m_agents.insert( identifier, thread );
thread->start();
}
void AgentServer::stopAgent( const QString &identifier )
{
if ( !m_agents.contains( identifier ) ) {
return;
}
AgentThread *thread = m_agents.take( identifier );
thread->quit();
thread->wait();
delete thread;
}
void AgentServer::quit()
{
Q_ASSERT( !m_quiting );
m_quiting = true;
QMutableHashIterator<QString, AgentThread *> it( m_agents );
while ( it.hasNext() ) {
it.next();
stopAgent( it.key() );
}
QCoreApplication::instance()->quit();
}
void AgentServer::processConfigureRequest()
{
if ( m_processingConfigureRequests ) {
return; // Protect against reentrancy
}
m_processingConfigureRequests = true;
while ( !m_configureQueue.empty() ) {
const ConfigureInfo info = m_configureQueue.dequeue();
// call configure on the agent with id info.first for windowId info.second.
Q_ASSERT( m_agents.contains( info.first ) );
AgentThread *thread = m_agents.value( info.first );
thread->configure( info.second );
}
m_processingConfigureRequests = false;
}

View file

@ -0,0 +1,64 @@
/*
Copyright (c) 2010 Volker Krause <vkrause@kde.org>
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
*/
#ifndef AKONADI_AGENTSERVER_H
#define AKONADI_AGENTSERVER_H
#include "agentpluginloader.h"
#include <QtCore/QHash>
#include <QtCore/QObject>
#include <QtCore/QQueue>
namespace Akonadi {
class AgentThread;
class AgentServer : public QObject
{
Q_OBJECT
Q_CLASSINFO( "D-Bus Interface", "org.freedesktop.Akonadi.AgentServer" )
typedef QPair<QString, qlonglong> ConfigureInfo;
public:
explicit AgentServer( QObject *parent = 0 );
~AgentServer();
public Q_SLOTS:
Q_SCRIPTABLE void agentInstanceConfigure( const QString &identifier, qlonglong windowId );
Q_SCRIPTABLE bool started( const QString &identifier ) const;
Q_SCRIPTABLE void startAgent( const QString &identifier, const QString &typeIdentifier, const QString &fileName );
Q_SCRIPTABLE void stopAgent( const QString &identifier );
Q_SCRIPTABLE void quit();
private Q_SLOTS:
void processConfigureRequest();
private:
QHash<QString, AgentThread *> m_agents;
QQueue<ConfigureInfo> m_configureQueue;
AgentPluginLoader m_agentLoader;
bool m_processingConfigureRequests;
bool m_quiting;
};
}
#endif

View file

@ -0,0 +1,63 @@
/*
Copyright (c) 2010 Volker Krause <vkrause@kde.org>
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
*/
#include "agentthread.h"
#include <QtCore/QCoreApplication>
#include <QtCore/QDebug>
#include <QtCore/QPluginLoader>
#include <QWidget> // Needed for WId
#include <shared/akdebug.h>
#include <qmetaobject.h>
using namespace Akonadi;
AgentThread::AgentThread( const QString &identifier, QObject *factory, QObject *parent )
: QThread( parent )
, m_identifier( identifier )
, m_factory( factory )
, m_instance( 0 )
{
}
void AgentThread::run()
{
const bool invokeSucceeded = QMetaObject::invokeMethod( m_factory,
"createInstance",
Qt::DirectConnection,
Q_RETURN_ARG( QObject*, m_instance ),
Q_ARG( QString, m_identifier ) );
if ( invokeSucceeded ) {
qDebug() << Q_FUNC_INFO << "agent instance created: " << m_instance;
} else {
qDebug() << Q_FUNC_INFO << "agent instance creation failed";
}
exec();
delete m_instance;
}
void AgentThread::configure( qlonglong windowId )
{
QMetaObject::invokeMethod( m_instance,
"configure",
Qt::DirectConnection,
Q_ARG( WId, (WId)windowId ) );
}

View file

@ -0,0 +1,62 @@
/*
Copyright (c) 2010 Volker Krause <vkrause@kde.org>
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
*/
#ifndef AKONADI_AGENTTHREAD_H
#define AKONADI_AGENTTHREAD_H
#include <QtCore/QThread>
namespace Akonadi {
/**
* @short A class that encapsulates an agent instance inside a thread.
*/
class AgentThread : public QThread
{
Q_OBJECT
public:
/**
* Creates a new agent thread.
*
* @param identifier The unique identifier for this agent
* @param factory The factory object that creates the agent instance.
* @param parent The parent object.
*/
AgentThread( const QString &identifier, QObject *factory, QObject *parent = 0 );
/**
* Configures the agent.
*
* @param windowId The parent window id for the config dialog.
*/
void configure( qlonglong windowId );
protected:
void run();
private:
QString m_identifier;
QObject *m_factory;
QObject *m_instance;
};
}
#endif

View file

@ -0,0 +1,50 @@
/*
Copyright (c) 2010 Volker Krause <vkrause@kde.org>
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
*/
#include "agentserver.h"
#include <shared/akapplication.h>
#include <shared/akdbus.h>
#include <shared/akdebug.h>
#include <QtDBus/QDBusConnection>
#include <QtDBus/QDBusConnectionInterface>
#include <QtDBus/QDBusError>
#include <QApplication>
int main( int argc, char **argv )
{
AkGuiApplication app( argc, argv );
app.setDescription( QLatin1String( "Akonadi Agent Server\nDo not run manually, use 'akonadictl' instead to start/stop Akonadi." ) );
app.parseCommandLine();
qApp->setQuitOnLastWindowClosed( false );
if ( !QDBusConnection::sessionBus().interface()->isServiceRegistered( AkDBus::serviceName( AkDBus::ControlLock ) ) ) {
akError() << "Akonadi control process not found - aborting.";
akFatal() << "If you started akonadi_agent_server manually, try 'akonadictl start' instead.";
}
new Akonadi::AgentServer( &app );
if ( !QDBusConnection::sessionBus().registerService( AkDBus::serviceName( AkDBus::AgentServer ) ) ) {
akFatal() << "Unable to connect to dbus service: " << QDBusConnection::sessionBus().lastError().message();
}
return app.exec();
}

35
akonadi/akonadi-mime.xml Normal file
View file

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
It comes with ABSOLUTELY NO WARRANTY, to the extent permitted by law. You may
redistribute copies of update-mime-database under the terms of the GNU General
Public License. For more information about these matters, see the file named
COPYING.
-->
<!--
Notes:
- the mime types in this file are valid with the version 0.20 of the
shared-mime-info package.
- the "fdo #xxxxx" are the wish in the freedesktop.org bug database to include
the mime type there.
-->
<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
<mime-type type="application/x-vnd.akonadi.calendar.event">
<sub-class-of type="text/calendar"/>
<comment>iCal Calendar Event Component</comment>
</mime-type>
<mime-type type="application/x-vnd.akonadi.calendar.freebusy">
<sub-class-of type="text/calendar"/>
<comment>iCal Calendar FreeBusy Component</comment>
</mime-type>
<mime-type type="application/x-vnd.akonadi.calendar.journal">
<sub-class-of type="text/calendar"/>
<comment>iCal Calendar Journal Component</comment>
</mime-type>
<mime-type type="application/x-vnd.akonadi.calendar.todo">
<sub-class-of type="text/calendar"/>
<comment>iCal Calendar TODO Component</comment>
</mime-type>
<mime-type type="application/x-vnd.akonadi.collection.virtual">
<comment>Virtual Akonadi Collection</comment>
</mime-type>
</mime-info>

View file

@ -0,0 +1,7 @@
/* This file contains all the paths that change when changing the installation prefix */
#define AKONADIPREFIX "${CMAKE_INSTALL_PREFIX}"
#define AKONADIDATA "${SHARE_INSTALL_PREFIX}"
#define AKONADICONFIG "${CONFIG_INSTALL_DIR}"
#define AKONADILIB "${LIB_INSTALL_DIR}"
#define AKONADIBUNDLEPATH "${AKONADI_BUNDLE_PATH}"

11
akonadi/akonadi.pc.cmake Normal file
View file

@ -0,0 +1,11 @@
prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=@CMAKE_INSTALL_PREFIX@
libdir=@LIB_INSTALL_DIR@
includedir=@CMAKE_INSTALL_PREFIX@/include
Name: Akonadi
Description: Akonadi server and infrastructure needed to build client libraries and applications
Version: @AKONADI_VERSION@
Requires: QtCore QtSql QtDBus
Libs: -L${libdir} -lakonadiprotocolinternals
Cflags: -I${includedir}

View file

@ -0,0 +1,15 @@
project(asapcat)
#set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${_ENABLE_EXCEPTIONS}" )
set(AKONADI_PROTOCOLINTERNALS_LIBS ${akonadiprotocolinternals_LIB_DEPENDS} akonadiprotocolinternals)
set(asapcat_srcs
main.cpp
session.cpp
)
add_executable(asapcat ${asapcat_srcs})
target_link_libraries(asapcat akonadi_shared ${QT_QTCORE_LIBRARY} ${QT_QTNETWORK_LIBRARY} ${AKONADI_PROTOCOLINTERNALS_LIBS} ${Boost_PROGRAM_OPTIONS_LIBRARY})
install(TARGETS asapcat DESTINATION ${BIN_INSTALL_DIR})

50
akonadi/asapcat/main.cpp Normal file
View file

@ -0,0 +1,50 @@
/***************************************************************************
* Copyright (C) 2013 by Volker Krause <vkrause@kde.org> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Library General Public License as *
* published by the Free Software Foundation; either version 2 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 Library General Public *
* License along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#include <session.h>
#include <shared/akapplication.h>
#include <shared/akstandarddirs.h>
#include <QCoreApplication>
#include <QDebug>
int main( int argc, char **argv )
{
AkCoreApplication app( argc, argv );
app.setDescription( QLatin1String( "Akonadi ASAP cat\n"
"This is a development tool, only use this if you know what you are doing.\n\n"
"Usage: asapcat [input]" ) );
boost::program_options::options_description options;
options.add_options()
( "input", boost::program_options::value<std::string>()->default_value( "-" ), "input to read commands from" );
app.addCommandLineOptions( options );
app.addPositionalCommandLineOption( "input", 1 );
app.parseCommandLine();
Session session( QString::fromStdString( app.commandLineArguments()["input"].as<std::string>() ) );
QObject::connect( &session, SIGNAL(disconnected()), QCoreApplication::instance(), SLOT(quit()) );
QMetaObject::invokeMethod( &session, "connectToHost", Qt::QueuedConnection );
const int result = app.exec();
session.printStats();
return result;
}

153
akonadi/asapcat/session.cpp Normal file
View file

@ -0,0 +1,153 @@
/***************************************************************************
* Copyright (C) 2013 by Volker Krause <vkrause@kde.org> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Library General Public License as *
* published by the Free Software Foundation; either version 2 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 Library General Public *
* License along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#include "session.h"
#include <shared/akstandarddirs.h>
#include <shared/akdebug.h>
#include <QCoreApplication>
#include <QDebug>
#include <QFile>
#include <QSocketNotifier>
#include <QSettings>
#include <QLocalSocket>
#include <iostream>
#include <fcntl.h>
#include <unistd.h>
Session::Session( const QString &input, QObject *parent )
: QObject( parent )
, m_input( 0 )
, m_session( 0 )
, m_notifier( 0 )
, m_receivedBytes( 0 )
, m_sentBytes( 0 )
{
QFile *file = new QFile( this );
if ( input != QLatin1String( "-" ) ) {
file->setFileName( input );
if ( !file->open( QFile::ReadOnly ) ) {
akFatal() << "Failed to open" << input;
}
} else {
// ### does that work on Windows?
const int flags = fcntl( 0, F_GETFL );
fcntl( 0, F_SETFL, flags | O_NONBLOCK );
if ( !file->open( stdin, QFile::ReadOnly|QFile::Unbuffered ) ) {
akFatal() << "Failed to open stdin!";
}
m_notifier = new QSocketNotifier( 0, QSocketNotifier::Read, this );
connect( m_notifier, SIGNAL(activated(int)), SLOT(inputAvailable()) );
}
m_input = file;
}
Session::~Session()
{
}
void Session::connectToHost()
{
const QSettings connectionSettings( AkStandardDirs::connectionConfigFile(), QSettings::IniFormat );
QString serverAddress;
#ifdef Q_OS_WIN
serverAddress = connectionSettings.value( QLatin1String( "Data/NamedPipe" ), QString() ).toString();
#else
serverAddress = connectionSettings.value( QLatin1String( "Data/UnixPath" ), QString() ).toString();
#endif
if ( serverAddress.isEmpty() ) {
akFatal() << "Unable to determine server address.";
}
QLocalSocket *socket = new QLocalSocket( this );
connect( socket, SIGNAL(error(QLocalSocket::LocalSocketError)), SLOT(serverError(QLocalSocket::LocalSocketError)) );
connect( socket, SIGNAL(disconnected()), SLOT(serverDisconnected()) );
connect( socket, SIGNAL(readyRead()), SLOT(serverRead()) );
connect( socket, SIGNAL(connected()), SLOT(inputAvailable()) );
m_session = socket;
socket->connectToServer( serverAddress );
m_connectionTime.start();
}
void Session::inputAvailable()
{
if ( !m_session->isOpen() ) {
return;
}
if ( m_notifier ) {
m_notifier->setEnabled( false );
}
if ( m_input->atEnd() ) {
return;
}
QByteArray buffer( 1024, Qt::Uninitialized );
qint64 readSize = 0;
while ( ( readSize = m_input->read( buffer.data(), buffer.size() ) ) > 0 ) {
m_session->write( buffer.constData(), readSize );
m_sentBytes += readSize;
}
if ( m_notifier ) {
m_notifier->setEnabled( true );
}
}
void Session::serverDisconnected()
{
QCoreApplication::exit( 0 );
}
void Session::serverError( QLocalSocket::LocalSocketError socketError )
{
if ( socketError == QLocalSocket::PeerClosedError ) {
QCoreApplication::exit( 0 );
return;
}
std::cerr << qPrintable( m_session->errorString() );
QCoreApplication::exit( 1 );
}
void Session::serverRead()
{
QByteArray buffer( 1024, Qt::Uninitialized );
qint64 readSize = 0;
while ( ( readSize = m_session->read( buffer.data(), buffer.size() ) ) > 0 ) {
write( 1, buffer.data(), readSize );
m_receivedBytes += readSize;
}
}
void Session::printStats() const
{
std::cerr << "Connection time: " << m_connectionTime.elapsed() << " ms" << std::endl;
std::cerr << "Sent: " << m_sentBytes << " bytes" << std::endl;
std::cerr << "Received: " << m_receivedBytes << " bytes" << std::endl;
}

62
akonadi/asapcat/session.h Normal file
View file

@ -0,0 +1,62 @@
/***************************************************************************
* Copyright (C) 2013 by Volker Krause <vkrause@kde.org> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Library General Public License as *
* published by the Free Software Foundation; either version 2 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 Library General Public *
* License along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#ifndef SESSION_H
#define SESSION_H
#include <QObject>
#include <QLocalSocket>
#include <QTime>
class QIODevice;
class QSocketNotifier;
/** ASAP CLI session. */
class Session : public QObject
{
Q_OBJECT
public:
explicit Session( const QString &input, QObject *parent = 0 );
~Session();
void printStats() const;
public Q_SLOTS:
void connectToHost();
Q_SIGNALS:
void disconnected();
private Q_SLOTS:
void inputAvailable();
void serverDisconnected();
void serverError( QLocalSocket::LocalSocketError socketError );
void serverRead();
private:
QIODevice *m_input;
QIODevice *m_session;
QSocketNotifier *m_notifier;
QTime m_connectionTime;
qint64 m_receivedBytes;
qint64 m_sentBytes;
};
#endif // SESSION_H

View file

@ -0,0 +1,4 @@
1 LOGIN asapcat
2 UID SELECT SILENT 471
3 FETCH 1:* CACHEONLY EXTERNALPAYLOAD (UID REMOTEID REMOTEREVISION COLLECTIONID FLAGS SIZE)
4 LOGOUT

View file

@ -0,0 +1,4 @@
1 LOGIN asapcat
2 UID SELECT SILENT 471
3 FETCH 1:* CACHEONLY CHECKCACHEDPARTSONLY EXTERNALPAYLOAD (UID REMOTEID REMOTEREVISION COLLECTIONID FLAGS SIZE PLD:RFC822)
4 LOGOUT

View file

@ -0,0 +1,5 @@
1 LOGIN asapcat
2 UID SELECT SILENT 471
3 FETCH 1:* IGNOREERRORS ANCESTORS INF EXTERNALPAYLOAD (UID REMOTEID REMOTEREVISION COLLECTIONID FLAGS SIZE DATETIME PLD:ENVELOPE)
4 LOGOUT

View file

@ -0,0 +1,5 @@
1 LOGIN asapcat
2 UID SELECT SILENT 471
3 FETCH 1:* IGNOREERRORS ANCESTORS INF EXTERNALPAYLOAD (UID REMOTEID REMOTEREVISION COLLECTIONID FLAGS SIZE PLD:ENVELOPE)
4 LOGOUT

View file

@ -0,0 +1,5 @@
1 LOGIN asapcat
2 UID SELECT SILENT 496
3 FETCH 1:* IGNOREERRORS ANCESTORS INF EXTERNALPAYLOAD (UID COLLECTIONID FLAGS SIZE PLD:ENVELOPE)
4 LOGOUT

View file

@ -0,0 +1,30 @@
# This is a very basic file for the new style find_package() search mode,
# i.e. Config-mode. It is used by MACRO_WRITE_BASIC_CMAKE_VERSION_FILE() from
# MacroWriteBasicCMakeVersionFile.cmake.
# In this mode find_package() searches for a <package>Config.cmake
# file and an associated <package>Version.cmake file, which it loads to check
# the version number.
# This file can be used with configure_file() to generate such a file for a project
# with very basic logic.
# It sets PACKAGE_VERSION_EXACT if the current version string and the requested
# version string are exactly the same and it sets PACKAGE_VERSION_COMPATIBLE
# if the current version is >= requested version.
# If this is not good enough for your project, you need to write your own
# improved <package>Version.cmake file.
# This file requires the following three variables to be set:
# PROJECT_VERSION_MAJOR
# PROJECT_VERSION_MINOR
# PROJECT_VERSION_PATCH
set(PACKAGE_VERSION @PROJECT_VERSION_MAJOR@.@PROJECT_VERSION_MINOR@.@PROJECT_VERSION_PATCH@)
if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" )
set(PACKAGE_VERSION_COMPATIBLE FALSE)
else("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" )
set(PACKAGE_VERSION_COMPATIBLE TRUE)
if( "${PACKAGE_FIND_VERSION}" STREQUAL "${PACKAGE_VERSION}")
set(PACKAGE_VERSION_EXACT TRUE)
endif( "${PACKAGE_FIND_VERSION}" STREQUAL "${PACKAGE_VERSION}")
endif("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" )

View file

@ -0,0 +1,22 @@
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View file

@ -0,0 +1,119 @@
#=============================================================================
# Copyright 2005-2011 Kitware, Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# * Neither the name of Kitware, Inc. nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#=============================================================================
# Portability helpers.
set(QT_QTGUI_LIBRARIES
${Qt5Gui_LIBRARIES}
${Qt5Widgets_LIBRARIES}
${Qt5PrintSupport_LIBRARIES}
${Qt5Svg_LIBRARIES}
)
set(QT_INCLUDES
${Qt5Gui_INCLUDE_DIRS}
${Qt5Widgets_INCLUDE_DIRS}
${Qt5PrintSupport_INCLUDE_DIRS}
${Qt5Svg_INCLUDE_DIRS}
)
set(_qt_modules
Core
Declarative
Widgets
Script
ScriptTools
DBus
Network
Test
Designer
Concurrent
Xml
UiTools
WebKit
Sql
OpenGL
)
foreach(_module ${_qt_modules})
string(TOUPPER ${_module} _module_upper)
set(QT_QT${_module_upper}_LIBRARIES ${Qt5${_module}_LIBRARIES})
set(QT_QT${_module_upper}_LIBRARY ${QT_QT${_module_upper}_LIBRARIES})
list(APPEND QT_INCLUDES ${Qt5${_module}_INCLUDE_DIRS})
set(QT_QT${_module_upper}_FOUND ${Qt5${_module}_FOUND})
endforeach()
get_target_property(QT_QMAKE_EXECUTABLE Qt5::qmake LOCATION)
get_target_property(QT_RCC_EXECUTABLE Qt5::rcc LOCATION)
if (TARGET Qt5::uic)
get_target_property(QT_UIC_EXECUTABLE Qt5::uic LOCATION)
endif()
if (TARGET Qt5::qdbuscpp2xml)
get_target_property(QT_QDBUSCPP2XML_EXECUTABLE Qt5::qdbuscpp2xml LOCATION)
endif()
if (TARGET Qt5::qdbusxml2cpp)
get_target_property(QT_QDBUSXML2CPP_EXECUTABLE Qt5::qdbusxml2cpp LOCATION)
endif()
macro(qt4_wrap_ui)
qt5_wrap_ui(${ARGN})
endmacro()
macro(qt4_wrap_cpp)
qt5_wrap_cpp(${ARGN})
endmacro()
macro(qt4_generate_moc)
qt5_generate_moc(${ARGN})
endmacro()
macro(qt4_add_dbus_adaptor)
qt5_add_dbus_adaptor(${ARGN})
endmacro()
macro(qt4_add_dbus_interfaces)
qt5_add_dbus_interfaces(${ARGN})
endmacro()
macro(qt4_add_dbus_interface)
qt5_add_dbus_interface(${ARGN})
endmacro()
macro(qt4_generate_dbus_interface)
qt5_generate_dbus_interface(${ARGN})
endmacro()
macro(qt4_add_resources)
qt5_add_resources(${ARGN})
endmacro()

View file

@ -0,0 +1,84 @@
# - Find provider for backtrace(3)
# Checks if OS supports backtrace(3) via either libc or custom library.
# This module defines the following variables:
# Backtrace_HEADER - The header file needed for backtrace(3). Cached.
# Could be forcibly set by user.
# Backtrace_INCLUDE_DIRS - The include directories needed to use backtrace(3) header.
# Backtrace_LIBRARIES - The libraries (linker flags) needed to use backtrace(3), if any.
# Backtrace_FOUND - Is set if and only if backtrace(3) support detected.
#
# The following cache variables are also available to set or use:
# Backtrace_LIBRARY - The external library providing backtrace, if any.
# Backtrace_INCLUDE_DIR - The directory holding the backtrace(3) header.
#
# Typical usage is to generate of header file using configure_file() with the
# contents like the following:
# #cmakedefine01 Backtrace_FOUND
# #if Backtrace_FOUND
# # include <${Backtrace_HEADER}>
# #endif
# And then reference that generated header file in actual source.
#=============================================================================
# Copyright (c) 2013, Vadim Zhukov <persgray@gmail.com>
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
include(CMakePushCheckState)
include(CheckSymbolExists)
include(FindPackageHandleStandardArgs)
# List of variables to be provided to find_package_handle_standard_args()
set(_Backtrace_STD_ARGS Backtrace_INCLUDE_DIR)
if(Backtrace_HEADER)
set(_Backtrace_HEADER_TRY "${Backtrace_HEADER}")
else(Backtrace_HEADER)
set(_Backtrace_HEADER_TRY "execinfo.h")
endif(Backtrace_HEADER)
find_path(Backtrace_INCLUDE_DIR "${_Backtrace_HEADER_TRY}")
set(Backtrace_INCLUDE_DIRS ${Backtrace_INCLUDE_DIR})
# First, check if we already have backtrace(), e.g., in libc
cmake_push_check_state(RESET)
set(CMAKE_REQUIRED_INCLUDES ${Backtrace_INCLUDE_DIRS})
check_symbol_exists("backtrace" "${_Backtrace_HEADER_TRY}" _Backtrace_SYM_FOUND)
cmake_pop_check_state()
if(_Backtrace_SYM_FOUND)
set(Backtrace_LIBRARY)
if(NOT Backtrace_FIND_QUIETLY)
message(STATUS "backtrace facility detected in default set of libraries")
endif()
else()
# Check for external library, for non-glibc systems
if(Backtrace_INCLUDE_DIR)
# OpenBSD has libbacktrace renamed to libexecinfo
find_library(Backtrace_LIBRARY "execinfo")
elseif() # respect user wishes
set(_Backtrace_HEADER_TRY "backtrace.h")
find_path(Backtrace_INCLUDE_DIR ${_Backtrace_HEADER_TRY})
find_library(Backtrace_LIBRARY "backtrace")
endif()
# Prepend list with library path as it's more common practice
set(_Backtrace_STD_ARGS Backtrace_LIBRARY ${_Backtrace_STD_ARGS})
endif()
set(Backtrace_LIBRARIES ${Backtrace_LIBRARY})
set(Backtrace_HEADER "${_Backtrace_HEADER_TRY}" CACHE STRING "Header providing backtrace(3) facility")
find_package_handle_standard_args(Backtrace FOUND_VAR Backtrace_FOUND REQUIRED_VARS ${_Backtrace_STD_ARGS})
mark_as_advanced(Backtrace_HEADER Backtrace_INCLUDE_DIR Backtrace_LIBRARY)

View file

@ -0,0 +1,113 @@
#
# FIND_LIBRARY_WITH_DEBUG
# -> enhanced FIND_LIBRARY to allow the search for an
# optional debug library with a WIN32_DEBUG_POSTFIX similar
# to CMAKE_DEBUG_POSTFIX when creating a shared lib
# it has to be the second and third argument
# Copyright (c) 2007, Christian Ehrlicher, <ch.ehrlicher@gmx.de>
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
MACRO(FIND_LIBRARY_WITH_DEBUG var_name win32_dbg_postfix_name dgb_postfix libname)
IF(NOT "${win32_dbg_postfix_name}" STREQUAL "WIN32_DEBUG_POSTFIX")
# no WIN32_DEBUG_POSTFIX -> simply pass all arguments to FIND_LIBRARY
FIND_LIBRARY(${var_name}
${win32_dbg_postfix_name}
${dgb_postfix}
${libname}
${ARGN}
)
ELSE(NOT "${win32_dbg_postfix_name}" STREQUAL "WIN32_DEBUG_POSTFIX")
IF(NOT WIN32)
# on non-win32 we don't need to take care about WIN32_DEBUG_POSTFIX
FIND_LIBRARY(${var_name} ${libname} ${ARGN})
ELSE(NOT WIN32)
# 1. get all possible libnames
SET(args ${ARGN})
SET(newargs "")
SET(libnames_release "")
SET(libnames_debug "")
LIST(LENGTH args listCount)
IF("${libname}" STREQUAL "NAMES")
SET(append_rest 0)
LIST(APPEND args " ")
FOREACH(i RANGE ${listCount})
LIST(GET args ${i} val)
IF(append_rest)
LIST(APPEND newargs ${val})
ELSE(append_rest)
IF("${val}" STREQUAL "PATHS")
LIST(APPEND newargs ${val})
SET(append_rest 1)
ELSE("${val}" STREQUAL "PATHS")
LIST(APPEND libnames_release "${val}")
LIST(APPEND libnames_debug "${val}${dgb_postfix}")
ENDIF("${val}" STREQUAL "PATHS")
ENDIF(append_rest)
ENDFOREACH(i)
ELSE("${libname}" STREQUAL "NAMES")
# just one name
LIST(APPEND libnames_release "${libname}")
LIST(APPEND libnames_debug "${libname}${dgb_postfix}")
SET(newargs ${args})
ENDIF("${libname}" STREQUAL "NAMES")
# search the release lib
FIND_LIBRARY(${var_name}_RELEASE
NAMES ${libnames_release}
${newargs}
)
# search the debug lib
FIND_LIBRARY(${var_name}_DEBUG
NAMES ${libnames_debug}
${newargs}
)
IF(${var_name}_RELEASE AND ${var_name}_DEBUG)
# both libs found
SET(${var_name} optimized ${${var_name}_RELEASE}
debug ${${var_name}_DEBUG})
ELSE(${var_name}_RELEASE AND ${var_name}_DEBUG)
IF(${var_name}_RELEASE)
# only release found
SET(${var_name} ${${var_name}_RELEASE})
ELSE(${var_name}_RELEASE)
# only debug (or nothing) found
SET(${var_name} ${${var_name}_DEBUG})
ENDIF(${var_name}_RELEASE)
ENDIF(${var_name}_RELEASE AND ${var_name}_DEBUG)
MARK_AS_ADVANCED(${var_name}_RELEASE)
MARK_AS_ADVANCED(${var_name}_DEBUG)
ENDIF(NOT WIN32)
ENDIF(NOT "${win32_dbg_postfix_name}" STREQUAL "WIN32_DEBUG_POSTFIX")
ENDMACRO(FIND_LIBRARY_WITH_DEBUG)

View file

@ -0,0 +1,67 @@
# - Try to find the shared-mime-info package
# Once done this will define
#
# SharedMimeInfo_FOUND - system has the shared-mime-info package
# UPDATE_MIME_DATABASE_EXECUTABLE - the update-mime-database executable
# Copyright (c) 2007, Pino Toscano, <toscano.pino@tiscali.it>
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
# the minimum version of shared-mime-database we require
if (NOT SHARED_MIME_INFO_MINIMUM_VERSION)
set(SHARED_MIME_INFO_MINIMUM_VERSION "0.18")
endif (NOT SHARED_MIME_INFO_MINIMUM_VERSION)
if (UPDATE_MIME_DATABASE_EXECUTABLE)
# in cache already
set(SharedMimeInfo_FOUND TRUE)
else (UPDATE_MIME_DATABASE_EXECUTABLE)
include (MacroEnsureVersion)
find_program (UPDATE_MIME_DATABASE_EXECUTABLE NAMES update-mime-database)
if (UPDATE_MIME_DATABASE_EXECUTABLE)
exec_program (${UPDATE_MIME_DATABASE_EXECUTABLE} ARGS -v RETURN_VALUE _null OUTPUT_VARIABLE _smiVersionRaw)
string(REGEX REPLACE "update-mime-database \\([a-zA-Z\\-]+\\) ([0-9]\\.[0-9]+).*"
"\\1" smiVersion "${_smiVersionRaw}")
set (SharedMimeInfo_FOUND TRUE)
endif (UPDATE_MIME_DATABASE_EXECUTABLE)
if (SharedMimeInfo_FOUND)
if (NOT SharedMimeInfo_FIND_QUIETLY)
message(STATUS "Found shared-mime-info version: ${smiVersion}")
macro_ensure_version(${SHARED_MIME_INFO_MINIMUM_VERSION} ${smiVersion} _smiVersion_OK)
if (NOT _smiVersion_OK)
message(FATAL_ERROR "The found version of shared-mime-info (${smiVersion}) is below the minimum required (${SHARED_MIME_INFO_MINIMUM_VERSION})")
endif (NOT _smiVersion_OK)
endif (NOT SharedMimeInfo_FIND_QUIETLY)
else (SharedMimeInfo_FOUND)
if (SharedMimeInfo_FIND_REQUIRED)
message(FATAL_ERROR "Could NOT find shared-mime-info. See http://freedesktop.org/wiki/Software/shared-mime-info.")
endif (SharedMimeInfo_FIND_REQUIRED)
endif (SharedMimeInfo_FOUND)
endif (UPDATE_MIME_DATABASE_EXECUTABLE)
macro(UPDATE_XDG_MIMETYPES _path)
get_filename_component(_xdgmimeDir "${_path}" NAME)
if("${_xdgmimeDir}" STREQUAL packages )
get_filename_component(_xdgmimeDir "${_path}" PATH)
else("${_xdgmimeDir}" STREQUAL packages )
set(_xdgmimeDir "${_path}")
endif("${_xdgmimeDir}" STREQUAL packages )
install(CODE "
set(DESTDIR_VALUE \"\$ENV{DESTDIR}\")
if (NOT DESTDIR_VALUE)
execute_process(COMMAND ${UPDATE_MIME_DATABASE_EXECUTABLE} ${_xdgmimeDir})
endif (NOT DESTDIR_VALUE)
")
endmacro (UPDATE_XDG_MIMETYPES)

View file

@ -0,0 +1,209 @@
#
# Find an installation of Soprano
#
# Sets the following variables:
# Soprano_FOUND - true is Soprano has been found
# SOPRANO_INCLUDE_DIR - The include directory
# SOPRANO_LIBRARIES - The Soprano core library to link to (libsoprano)
# SOPRANO_INDEX_LIBRARIES - The Soprano index library (libsopranoindex)
# SOPRANO_CLIENT_LIBRARIES - The Soprano client library (libsopranoclient)
# SOPRANO_SERVER_LIBRARIES - The Soprano server library (libsopranoserver)
# SOPRANO_VERSION - The Soprano version (string value)
#
# SOPRANO_PLUGIN_NQUADPARSER_FOUND - true if the nquadparser plugin is found
# SOPRANO_PLUGIN_NQUADSERIALIZER_FOUND - true if the nquadserializer plugin is found
# SOPRANO_PLUGIN_RAPTORPARSER_FOUND - true if the raptorparser plugin is found
# SOPRANO_PLUGIN_RAPTORSERIALIZER_FOUND - true if the raptorserializer plugin is found
# SOPRANO_PLUGIN_REDLANDBACKEND_FOUND - true if the redlandbackend plugin is found
# SOPRANO_PLUGIN_SESAME2BACKEND_FOUND - true if the sesame2backend plugin is found
# SOPRANO_PLUGIN_VIRTUOSOBACKEND_FOUND - true if the virtuosobackend plugin is found
#
# Options:
# Set SOPRANO_MIN_VERSION to set the minimum required Soprano version (default: 1.99)
#
# Copyright (c) 2008, Sebastian Trueg, <sebastian@trueg.de>
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
include(FindLibraryWithDebug)
# have packageconfig set variables to find Soprano:
# package config dirs are used as secondary search paths after install_dir
find_package(PkgConfig)
if (PKG_CONFIG_FOUND)
pkg_check_modules(Soprano_PKGCONF soprano)
endif()
find_path(SOPRANO_INCLUDE_DIR
NAMES
soprano/soprano.h
HINTS
${INCLUDE_INSTALL_DIR}
${Soprano_PKGCONF_INCLUDE_DIRS}
)
find_library_with_debug(SOPRANO_INDEX_LIBRARIES
WIN32_DEBUG_POSTFIX d
NAMES
sopranoindex
HINTS
${LIB_INSTALL_DIR}
${Soprano_PKGCONF_LIBRARY_DIRS}
)
find_library_with_debug(SOPRANO_CLIENT_LIBRARIES
WIN32_DEBUG_POSTFIX d
NAMES
sopranoclient
HINTS
${LIB_INSTALL_DIR}
${Soprano_PKGCONF_LIBRARY_DIRS}
)
find_library_with_debug(SOPRANO_LIBRARIES
WIN32_DEBUG_POSTFIX d
NAMES soprano
HINTS
${LIB_INSTALL_DIR}
${Soprano_PKGCONF_LIBRARY_DIRS}
)
find_library_with_debug(SOPRANO_SERVER_LIBRARIES
WIN32_DEBUG_POSTFIX d
NAMES
sopranoserver
HINTS
${LIB_INSTALL_DIR}
${Soprano_PKGCONF_LIBRARY_DIRS}
)
# check for all the libs as required to make sure that we do not try to compile with an old version
if(SOPRANO_INCLUDE_DIR AND SOPRANO_LIBRARIES)
set(Soprano_FOUND TRUE)
endif(SOPRANO_INCLUDE_DIR AND SOPRANO_LIBRARIES)
if(Soprano_FOUND AND SOPRANO_INDEX_LIBRARIES)
set(SopranoIndex_FOUND TRUE)
endif(Soprano_FOUND AND SOPRANO_INDEX_LIBRARIES)
if(Soprano_FOUND AND SOPRANO_CLIENT_LIBRARIES)
set(SopranoClient_FOUND TRUE)
endif(Soprano_FOUND AND SOPRANO_CLIENT_LIBRARIES)
if(Soprano_FOUND AND SOPRANO_SERVER_LIBRARIES)
set(SopranoServer_FOUND TRUE)
endif(Soprano_FOUND AND SOPRANO_SERVER_LIBRARIES)
# check Soprano version
# We set a default for the minimum required version to be backwards compatible
if(NOT SOPRANO_MIN_VERSION)
set(SOPRANO_MIN_VERSION "1.99")
endif(NOT SOPRANO_MIN_VERSION)
if(Soprano_FOUND)
file(READ ${SOPRANO_INCLUDE_DIR}/soprano/version.h SOPRANO_VERSION_CONTENT)
string(REGEX MATCH "SOPRANO_VERSION_STRING \".*\"\n" SOPRANO_VERSION_MATCH ${SOPRANO_VERSION_CONTENT})
if(SOPRANO_VERSION_MATCH)
string(REGEX REPLACE "SOPRANO_VERSION_STRING \"(.*)\"\n" "\\1" SOPRANO_VERSION ${SOPRANO_VERSION_MATCH})
if(SOPRANO_VERSION STRLESS "${SOPRANO_MIN_VERSION}")
set(Soprano_FOUND FALSE)
if(Soprano_FIND_REQUIRED)
message(FATAL_ERROR "Soprano version ${SOPRANO_VERSION} is too old. Please install ${SOPRANO_MIN_VERSION} or newer")
else(Soprano_FIND_REQUIRED)
message(STATUS "Soprano version ${SOPRANO_VERSION} is too old. Please install ${SOPRANO_MIN_VERSION} or newer")
endif(Soprano_FIND_REQUIRED)
endif(SOPRANO_VERSION STRLESS "${SOPRANO_MIN_VERSION}")
endif(SOPRANO_VERSION_MATCH)
endif(Soprano_FOUND)
#look for parser plugins
if(Soprano_FOUND)
find_path(SOPRANO_PLUGIN_DIR
NAMES
soprano/plugins
PATHS
${SOPRANO_INCLUDE_DIR}/../share
${SHARE_INSTALL_PREFIX}
/usr/share
/usr/local/share
NO_DEFAULT_PATH
NO_SYSTEM_ENVIRONMENT_PATH
)
set(SOPRANO_PLUGIN_DIR "${SOPRANO_PLUGIN_DIR}/soprano/plugins")
if(EXISTS ${SOPRANO_PLUGIN_DIR}/nquadparser.desktop)
set(SOPRANO_PLUGIN_NQUADPARSER_FOUND TRUE)
set(_plugins "${_plugins} nquadparser")
endif(EXISTS ${SOPRANO_PLUGIN_DIR}/nquadparser.desktop)
if(EXISTS ${SOPRANO_PLUGIN_DIR}/nquadserializer.desktop)
set(SOPRANO_PLUGIN_NQUADSERIALIZER_FOUND TRUE)
set(_plugins "${_plugins} nquadserializer")
endif(EXISTS ${SOPRANO_PLUGIN_DIR}/nquadserializer.desktop)
if(EXISTS ${SOPRANO_PLUGIN_DIR}/raptorparser.desktop)
set(SOPRANO_PLUGIN_RAPTORPARSER_FOUND TRUE)
set(_plugins "${_plugins} raptorparser")
endif(EXISTS ${SOPRANO_PLUGIN_DIR}/raptorparser.desktop)
if(EXISTS ${SOPRANO_PLUGIN_DIR}/raptorserializer.desktop)
set(SOPRANO_PLUGIN_RAPTORSERIALIZER_FOUND TRUE)
set(_plugins "${_plugins} raptorserializer")
endif(EXISTS ${SOPRANO_PLUGIN_DIR}/raptorserializer.desktop)
if(EXISTS ${SOPRANO_PLUGIN_DIR}/redlandbackend.desktop)
set(SOPRANO_PLUGIN_REDLANDBACKEND_FOUND TRUE)
set(_plugins "${_plugins} redlandbackend")
endif(EXISTS ${SOPRANO_PLUGIN_DIR}/redlandbackend.desktop)
if(EXISTS ${SOPRANO_PLUGIN_DIR}/sesame2backend.desktop)
set(SOPRANO_PLUGIN_SESAME2BACKEND_FOUND TRUE)
set(_plugins "${_plugins} sesame2backend")
endif(EXISTS ${SOPRANO_PLUGIN_DIR}/sesame2backend.desktop)
if(EXISTS ${SOPRANO_PLUGIN_DIR}/virtuosobackend.desktop)
set(SOPRANO_PLUGIN_VIRTUOSOBACKEND_FOUND TRUE)
set(_plugins "${_plugins} virtuosobackend")
endif(EXISTS ${SOPRANO_PLUGIN_DIR}/virtuosobackend.desktop)
endif(Soprano_FOUND)
if(Soprano_FOUND)
if(NOT Soprano_FIND_QUIETLY)
message(STATUS "Found Soprano version ${SOPRANO_VERSION}: ${SOPRANO_LIBRARIES}")
message(STATUS "Found Soprano includes: ${SOPRANO_INCLUDE_DIR}")
message(STATUS "Found Soprano Index: ${SOPRANO_INDEX_LIBRARIES}")
message(STATUS "Found Soprano Client: ${SOPRANO_CLIENT_LIBRARIES}")
message(STATUS "Found Soprano Plugin Dir: ${SOPRANO_PLUGIN_DIR}")
message(STATUS "Found Soprano Plugins:${_plugins}")
endif(NOT Soprano_FIND_QUIETLY)
else(Soprano_FOUND)
if(Soprano_FIND_REQUIRED)
if(NOT SOPRANO_INCLUDE_DIR)
message(FATAL_ERROR "Could not find Soprano includes.")
endif(NOT SOPRANO_INCLUDE_DIR)
if(NOT SOPRANO_LIBRARIES)
message(FATAL_ERROR "Could not find Soprano library.")
endif(NOT SOPRANO_LIBRARIES)
else(Soprano_FIND_REQUIRED)
if(NOT SOPRANO_INCLUDE_DIR)
message(STATUS "Could not find Soprano includes.")
endif(NOT SOPRANO_INCLUDE_DIR)
if(NOT SOPRANO_LIBRARIES)
message(STATUS "Could not find Soprano library.")
endif(NOT SOPRANO_LIBRARIES)
endif(Soprano_FIND_REQUIRED)
endif(Soprano_FOUND)
mark_as_advanced(SOPRANO_CLIENT_LIBRARIES
SOPRANO_INDEX_LIBRARIES
SOPRANO_LIBRARIES
SOPRANO_SERVER_LIBRARIES
SOPRANO_INCLUDE_DIR
SOPRANO_PLUGIN_DIR)

View file

@ -0,0 +1,113 @@
# - Try to find Sqlite
# Once done this will define
#
# SQLITE_FOUND - system has Sqlite
# SQLITE_INCLUDE_DIR - the Sqlite include directory
# SQLITE_LIBRARIES - Link these to use Sqlite
# SQLITE_MIN_VERSION - The minimum SQLite version
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
#
# Copyright (c) 2008, Gilles Caulier, <caulier.gilles@gmail.com>
# Copyright (c) 2010, Christophe Giboudeaux, <cgiboudeaux@gmail.com>
# Copyright (c) 2014, Daniel Vrátil <dvratil@redhat.com>
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
if(NOT SQLITE_MIN_VERSION)
set(SQLITE_MIN_VERSION "3.6.16")
endif(NOT SQLITE_MIN_VERSION)
if ( SQLITE_INCLUDE_DIR AND SQLITE_LIBRARIES )
# in cache already
SET(Sqlite_FIND_QUIETLY TRUE)
endif ( SQLITE_INCLUDE_DIR AND SQLITE_LIBRARIES )
# use pkg-config to get the directories and then use these values
# in the FIND_PATH() and FIND_LIBRARY() calls
if( NOT WIN32 )
find_package(PkgConfig)
pkg_check_modules(PC_SQLITE sqlite3)
set(SQLITE_DEFINITIONS ${PC_SQLITE_CFLAGS_OTHER})
endif( NOT WIN32 )
if(PC_SQLITE_FOUND)
find_path(SQLITE_INCLUDE_DIR
NAMES sqlite3.h
PATHS ${PC_SQLITE_INCLUDEDIR}
NO_DEFAULT_PATH
)
find_library(SQLITE_LIBRARIES
NAMES sqlite3
PATHS ${PC_SQLITE_LIBDIR}
NO_DEFAULT_PATH
)
else(PC_SQLITE_FOUND)
find_path(SQLITE_INCLUDE_DIR
NAMES sqlite3.h
)
find_library(SQLITE_LIBRARIES
NAMES sqlite3
)
endif(PC_SQLITE_FOUND)
if( UNIX )
find_file(SQLITE_STATIC_LIBRARIES
libsqlite3.a
${PC_SQLITE_LIBDIR}
)
else( UNIX )
# todo find static libs for other systems
# fallback to standard libs
set( SQLITE_STATIC_LIBRARIES ${SQLITE_LIBRARIES} )
endif( UNIX )
if(EXISTS ${SQLITE_INCLUDE_DIR}/sqlite3.h)
file(READ ${SQLITE_INCLUDE_DIR}/sqlite3.h SQLITE3_H_CONTENT)
string(REGEX MATCH "SQLITE_VERSION[ ]*\"[0-9.]*\"\n" SQLITE_VERSION_MATCH "${SQLITE3_H_CONTENT}")
if(SQLITE_VERSION_MATCH)
string(REGEX REPLACE ".*SQLITE_VERSION[ ]*\"(.*)\"\n" "\\1" SQLITE_VERSION ${SQLITE_VERSION_MATCH})
if(SQLITE_VERSION VERSION_LESS "${SQLITE_MIN_VERSION}")
message(STATUS "Sqlite ${SQLITE_VERSION} was found, but at least version ${SQLITE_MIN_VERSION} is required")
set(SQLITE_VERSION_OK FALSE)
else(SQLITE_VERSION VERSION_LESS "${SQLITE_MIN_VERSION}")
set(SQLITE_VERSION_OK TRUE)
endif(SQLITE_VERSION VERSION_LESS "${SQLITE_MIN_VERSION}")
endif(SQLITE_VERSION_MATCH)
if (SQLITE_VERSION_OK)
file(WRITE ${CMAKE_BINARY_DIR}/sqlite_check_unlock_notify.cpp
"#include <sqlite3.h>
int main(int argc, char **argv) {
return sqlite3_unlock_notify(0, 0, 0);
}")
try_compile(SQLITE_HAS_UNLOCK_NOTIFY
${CMAKE_BINARY_DIR}/sqlite_check_unlock_notify
${CMAKE_BINARY_DIR}/sqlite_check_unlock_notify.cpp
LINK_LIBRARIES ${SQLITE_LIBRARIES}
CMAKE_FLAGS INCLUDE_DIRECTORIES ${SQLITE_INCLUDE_DIR})
if (NOT SQLITE_HAS_UNLOCK_NOTIFY)
message(STATUS "Sqlite ${SQLITE_VERSION} was found, but it is not compiled with -DSQLITE_ENABLE_UNLOCK_NOTIFY")
endif()
endif()
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args( Sqlite DEFAULT_MSG
SQLITE_INCLUDE_DIR
SQLITE_LIBRARIES
SQLITE_VERSION_OK
SQLITE_HAS_UNLOCK_NOTIFY)
# show the SQLITE_INCLUDE_DIR and SQLITE_LIBRARIES variables only in the advanced view
mark_as_advanced( SQLITE_INCLUDE_DIR SQLITE_LIBRARIES )

View file

@ -0,0 +1,90 @@
# Copyright (c) 2008 Kevin Krammer <kevin.krammer@gmx.at>
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
set (LIB_SUFFIX "" CACHE STRING "Define suffix of directory name (32/64)")
if (WIN32)
# use relative install prefix to avoid hardcoded install paths in cmake_install.cmake files
set (EXEC_INSTALL_PREFIX "") # Base directory for executables and libraries
## ${CMAKE_INSTALL_PREFIX}/*
set (BIN_INSTALL_DIR "bin") # The install dir for executables (default ${EXEC_INSTALL_PREFIX}/bin)
set (INCLUDE_INSTALL_DIR "include") # The subdirectory to the header prefix
set (LIB_INSTALL_DIR "lib${LIB_SUFFIX}") # The subdirectory relative to the install prefix where libraries will be installed (default is ${EXEC_INSTALL_PREFIX}/lib${LIB_SUFFIX})
set (SHARE_INSTALL_PREFIX "share") # Base directory for files which go to share/
## ${CMAKE_INSTALL_PREFIX}/share/*
set (CONFIG_INSTALL_DIR "share/config") # The config file install dir
set (DBUS_INTERFACES_INSTALL_DIR "share/dbus-1/interfaces") # The DBus interfaces install dir (default ${SHARE_INSTALL_PREFIX}/dbus-1/interfaces)")
set (DBUS_SERVICES_INSTALL_DIR "share/dbus-1/services") # The DBus services install dir (default ${SHARE_INSTALL_PREFIX}/dbus-1/services)")
set (XDG_MIME_INSTALL_DIR "share/mime/packages") # The install dir for the xdg mimetypes
else (WIN32)
# this macro implements some very special logic how to deal with the cache
# by default the various install locations inherit their value from theit "parent" variable
# so if you set CMAKE_INSTALL_PREFIX, then EXEC_INSTALL_PREFIX, PLUGIN_INSTALL_DIR will
# calculate their value by appending subdirs to CMAKE_INSTALL_PREFIX
# this would work completely without using the cache.
# but if somebody wants e.g. a different EXEC_INSTALL_PREFIX this value has to go into
# the cache, otherwise it will be forgotten on the next cmake run.
# Once a variable is in the cache, it doesn't depend on its "parent" variables
# anymore and you can only change it by editing it directly.
# this macro helps in this regard, because as long as you don't set one of the
# variables explicitely to some location, it will always calculate its value from its
# parents. So modifying CMAKE_INSTALL_PREFIX later on will have the desired effect.
# But once you decide to set e.g. EXEC_INSTALL_PREFIX to some special location
# this will go into the cache and it will no longer depend on CMAKE_INSTALL_PREFIX.
macro(_SET_FANCY _var _value _comment)
SET (predefinedvalue "${_value}")
if (NOT DEFINED ${_var})
SET (${_var} ${predefinedvalue})
else (NOT DEFINED ${_var})
SET (${_var} "${${_var}}" CACHE PATH "${_comment}")
endif (NOT DEFINED ${_var})
endmacro()
_set_fancy(EXEC_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}" "Base directory for executables and libraries")
## ${CMAKE_INSTALL_PREFIX}/*
_set_fancy(BIN_INSTALL_DIR "${EXEC_INSTALL_PREFIX}/bin" "The install dir for executables (default ${EXEC_INSTALL_PREFIX}/bin)")
_set_fancy(INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/include" "The subdirectory to the header prefix")
_set_fancy(LIB_INSTALL_DIR "${EXEC_INSTALL_PREFIX}/lib${LIB_SUFFIX}" "The subdirectory relative to the install prefix where libraries will be installed (default is ${EXEC_INSTALL_PREFIX}/lib${LIB_SUFFIX})")
_set_fancy(SHARE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}/share" "Base directory for files which go to share/")
## ${CMAKE_INSTALL_PREFIX}/share/*
_set_fancy(CONFIG_INSTALL_DIR "${SHARE_INSTALL_PREFIX}/config" "The config file install dir")
_set_fancy(DBUS_INTERFACES_INSTALL_DIR "${SHARE_INSTALL_PREFIX}/dbus-1/interfaces" "The DBus interfaces install dir (default ${SHARE_INSTALL_PREFIX}/dbus-1/interfaces)")
_set_fancy(DBUS_SERVICES_INSTALL_DIR "${SHARE_INSTALL_PREFIX}/dbus-1/services" "The DBus services install dir (default ${SHARE_INSTALL_PREFIX}/dbus-1/services)")
_set_fancy(XDG_MIME_INSTALL_DIR "${SHARE_INSTALL_PREFIX}/mime/packages" "The install dir for the xdg mimetypes")
endif (WIN32)
# The INSTALL_TARGETS_DEFAULT_ARGS variable should be used when libraries are installed.
# The arguments are also ok for regular executables, i.e. executables which don't go
# into sbin/ or libexec/, but for installing executables the basic syntax
# INSTALL(TARGETS kate DESTINATION "${BIN_INSTALL_DIR}")
# is enough, so using this variable there doesn't help a lot.
# The variable must not be used for installing plugins.
# Usage is like this:
# install(TARGETS kdecore kdeui ${INSTALL_TARGETS_DEFAULT_ARGS})
#
# This will install libraries correctly under UNIX, OSX and Windows (i.e. dll's go
# into bin/.
# Later on it will be possible to extend this for installing OSX frameworks
# The COMPONENT Devel argument has the effect that static libraries belong to the
# "Devel" install component. If we use this also for all install() commands
# for header files, it will be possible to install
# -everything: make install OR cmake -P cmake_install.cmake
# -only the development files: cmake -DCOMPONENT=Devel -P cmake_install.cmake
# -everything except the development files: cmake -DCOMPONENT=Unspecified -P cmake_install.cmake
# This can then also be used for packaging with cpack.
SET (INSTALL_TARGETS_DEFAULT_ARGS RUNTIME DESTINATION "${BIN_INSTALL_DIR}"
LIBRARY DESTINATION "${LIB_INSTALL_DIR}"
ARCHIVE DESTINATION "${LIB_INSTALL_DIR}" COMPONENT Devel)

View file

@ -0,0 +1,117 @@
# This file defines the following macros for developers to use in ensuring
# that installed software is of the right version:
#
# MACRO_ENSURE_VERSION - test that a version number is greater than
# or equal to some minimum
# MACRO_ENSURE_VERSION_RANGE - test that a version number is greater than
# or equal to some minimum and less than some
# maximum
# MACRO_ENSURE_VERSION2 - deprecated, do not use in new code
#
# MACRO_ENSURE_VERSION
# This macro compares version numbers of the form "x.y.z" or "x.y"
# MACRO_ENSURE_VERSION( FOO_MIN_VERSION FOO_VERSION_FOUND FOO_VERSION_OK)
# will set FOO_VERSION_OK to true if FOO_VERSION_FOUND >= FOO_MIN_VERSION
# Leading and trailing text is ok, e.g.
# MACRO_ENSURE_VERSION( "2.5.31" "flex 2.5.4a" VERSION_OK)
# which means 2.5.31 is required and "flex 2.5.4a" is what was found on the system
# Copyright (c) 2006, David Faure, <faure@kde.org>
# Copyright (c) 2007, Will Stephenson <wstephenson@kde.org>
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
# MACRO_ENSURE_VERSION_RANGE
# This macro ensures that a version number of the form
# "x.y.z" or "x.y" falls within a range defined by
# min_version <= found_version < max_version.
# If this expression holds, FOO_VERSION_OK will be set TRUE
#
# Example: MACRO_ENSURE_VERSION_RANGE3( "0.1.0" ${FOOCODE_VERSION} "0.7.0" FOO_VERSION_OK )
#
# This macro will break silently if any of x,y,z are greater than 100.
#
# Copyright (c) 2007, Will Stephenson <wstephenson@kde.org>
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
# NORMALIZE_VERSION
# Helper macro to convert version numbers of the form "x.y.z"
# to an integer equal to 10^4 * x + 10^2 * y + z
#
# This macro will break silently if any of x,y,z are greater than 100.
#
# Copyright (c) 2006, David Faure, <faure@kde.org>
# Copyright (c) 2007, Will Stephenson <wstephenson@kde.org>
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
# CHECK_RANGE_INCLUSIVE_LOWER
# Helper macro to check whether x <= y < z
#
# Copyright (c) 2007, Will Stephenson <wstephenson@kde.org>
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
MACRO(NORMALIZE_VERSION _requested_version _normalized_version)
STRING(REGEX MATCH "[^0-9]*[0-9]+\\.[0-9]+\\.[0-9]+.*" _threePartMatch "${_requested_version}")
if (_threePartMatch)
# parse the parts of the version string
STRING(REGEX REPLACE "[^0-9]*([0-9]+)\\.[0-9]+\\.[0-9]+.*" "\\1" _major_vers "${_requested_version}")
STRING(REGEX REPLACE "[^0-9]*[0-9]+\\.([0-9]+)\\.[0-9]+.*" "\\1" _minor_vers "${_requested_version}")
STRING(REGEX REPLACE "[^0-9]*[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" _patch_vers "${_requested_version}")
else (_threePartMatch)
STRING(REGEX REPLACE "([0-9]+)\\.[0-9]+" "\\1" _major_vers "${_requested_version}")
STRING(REGEX REPLACE "[0-9]+\\.([0-9]+)" "\\1" _minor_vers "${_requested_version}")
set(_patch_vers "0")
endif (_threePartMatch)
# compute an overall version number which can be compared at once
MATH(EXPR ${_normalized_version} "${_major_vers}*10000 + ${_minor_vers}*100 + ${_patch_vers}")
ENDMACRO(NORMALIZE_VERSION)
MACRO(MACRO_CHECK_RANGE_INCLUSIVE_LOWER _lower_limit _value _upper_limit _ok)
if (${_value} LESS ${_lower_limit})
set( ${_ok} FALSE )
elseif (${_value} EQUAL ${_lower_limit})
set( ${_ok} TRUE )
elseif (${_value} EQUAL ${_upper_limit})
set( ${_ok} FALSE )
elseif (${_value} GREATER ${_upper_limit})
set( ${_ok} FALSE )
else (${_value} LESS ${_lower_limit})
set( ${_ok} TRUE )
endif (${_value} LESS ${_lower_limit})
ENDMACRO(MACRO_CHECK_RANGE_INCLUSIVE_LOWER)
MACRO(MACRO_ENSURE_VERSION requested_version found_version var_too_old)
NORMALIZE_VERSION( ${requested_version} req_vers_num )
NORMALIZE_VERSION( ${found_version} found_vers_num )
if (found_vers_num LESS req_vers_num)
set( ${var_too_old} FALSE )
else (found_vers_num LESS req_vers_num)
set( ${var_too_old} TRUE )
endif (found_vers_num LESS req_vers_num)
ENDMACRO(MACRO_ENSURE_VERSION)
MACRO(MACRO_ENSURE_VERSION2 requested_version2 found_version2 var_too_old2)
MACRO_ENSURE_VERSION( ${requested_version2} ${found_version2} ${var_too_old2})
ENDMACRO(MACRO_ENSURE_VERSION2)
MACRO(MACRO_ENSURE_VERSION_RANGE min_version found_version max_version var_ok)
NORMALIZE_VERSION( ${min_version} req_vers_num )
NORMALIZE_VERSION( ${found_version} found_vers_num )
NORMALIZE_VERSION( ${max_version} max_vers_num )
MACRO_CHECK_RANGE_INCLUSIVE_LOWER( ${req_vers_num} ${found_vers_num} ${max_vers_num} ${var_ok})
ENDMACRO(MACRO_ENSURE_VERSION_RANGE)

View file

@ -0,0 +1,56 @@
CMake - Cross Platform Makefile Generator
Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the names of Kitware, Inc., the Insight Software Consortium,
nor the names of their contributors may be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
------------------------------------------------------------------------------
The above copyright and license notice applies to distributions of
CMake in source and binary form. Some source files contain additional
notices of original copyright by their contributors; see each source
for details. Third-party software packages supplied with CMake under
compatible licenses provide their own copyright notices documented in
corresponding subdirectories.
------------------------------------------------------------------------------
CMake was initially developed by Kitware with the following sponsorship:
* National Library of Medicine at the National Institutes of Health
as part of the Insight Segmentation and Registration Toolkit (ITK).
* US National Labs (Los Alamos, Livermore, Sandia) ASC Parallel
Visualization Initiative.
* National Alliance for Medical Image Computing (NAMIC) is funded by the
National Institutes of Health through the NIH Roadmap for Medical Research,
Grant U54 EB005149.
* Kitware, Inc.

View file

@ -0,0 +1,14 @@
#cmakedefine01 Backtrace_FOUND
#if Backtrace_FOUND
# include <@Backtrace_HEADER@>
#endif
#cmakedefine HAVE_UNISTD_H 1
#cmakedefine HAVE_SOPRANO 1
#define AKONADI_VERSION_MAJOR @AKONADI_VERSION_MAJOR@
#define AKONADI_VERSION_MINOR @AKONADI_VERSION_MINOR@
#define AKONADI_VERSION_PATCH @AKONADI_VERSION_PATCH@
#define AKONADI_VERSION_STRING "@AKONADI_VERSION_STRING@"
#define AKONADI_DATABASE_BACKEND "@AKONADI_DATABASE_BACKEND@"

View file

@ -0,0 +1,20 @@
SET(DBUS_INTERFACE_XMLS
org.freedesktop.Akonadi.AgentManager.xml
org.freedesktop.Akonadi.NotificationManager.xml
org.freedesktop.Akonadi.Preprocessor.xml
org.freedesktop.Akonadi.Tracer.xml
org.freedesktop.Akonadi.Agent.Control.xml
org.freedesktop.Akonadi.Agent.Search.xml
org.freedesktop.Akonadi.Agent.Status.xml
org.freedesktop.Akonadi.Resource.xml
org.freedesktop.Akonadi.ControlManager.xml
org.freedesktop.Akonadi.NotificationSource.xml
org.freedesktop.Akonadi.Server.xml
org.freedesktop.Akonadi.StorageDebugger.xml
org.freedesktop.Akonadi.TracerNotification.xml
)
install(FILES ${DBUS_INTERFACE_XMLS}
DESTINATION ${DBUS_INTERFACES_INSTALL_DIR})

View file

@ -0,0 +1,19 @@
<!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.freedesktop.Akonadi.Agent.Control">
<method name="quit">
</method>
<method name="cleanup">
</method>
<method name="configure">
<arg name="windowId" type="x" direction="in"/>
<annotation name="org.freedesktop.DBus.Method.NoReply" value="true"/>
</method>
<signal name="configurationDialogAccepted"/>
<signal name="configurationDialogRejected"/>
<method name="reconfigure">
</method>
<method name="abort">
</method>
</interface>
</node>

View file

@ -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.freedesktop.Akonadi.Agent.Search">
<method name="addSearch">
<arg name="query" type="s" direction="in"/>
<arg name="queryLanguage" type="s" direction="in"/>
<arg name="destination" type="x" direction="in"/>
<annotation name="org.freedesktop.DBus.Method.NoReply" value="true"/>
</method>
<method name="removeSearch">
<arg name="destination" type="x" direction="in"/>
<annotation name="org.freedesktop.DBus.Method.NoReply" value="true"/>
</method>
<method name="search">
<arg name="searchId" type="ay" direction="in"/>
<arg name="query" type="s" direction="in"/>
<arg name="collection" type="x" direction="in"/>
<annotation name="org.freedesktop.DBus.Method.NoReply" value="true"/>
</method>
</interface>
</node>

View file

@ -0,0 +1,41 @@
<!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.freedesktop.Akonadi.Agent.Status">
<signal name="status">
<arg name="status" type="i" direction="out"/>
<arg name="message" type="s" direction="out"/>
</signal>
<signal name="percent">
<arg name="percent" type="i" direction="out"/>
</signal>
<signal name="warning">
<arg name="message" type="s" direction="out"/>
</signal>
<signal name="error">
<arg name="message" type="s" direction="out"/>
</signal>
<signal name="onlineChanged">
<arg name="state" type="b" direction="out"/>
</signal>
<signal name="advancedStatus">
<annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="QVariantMap"/>
<arg name="status" type="a{sv}" direction="out"/>
</signal>
<method name="status">
<arg type="i" direction="out"/>
</method>
<method name="statusMessage">
<arg type="s" direction="out"/>
</method>
<method name="progress">
<arg type="i" direction="out"/>
</method>
<method name="isOnline">
<arg type="b" direction="out"/>
</method>
<method name="setOnline">
<arg name="state" type="b" direction="in"/>
<annotation name="org.freedesktop.DBus.Method.NoReply" value="true"/>
</method>
</interface>
</node>

View file

@ -0,0 +1,160 @@
<!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.freedesktop.Akonadi.AgentManager">
<signal name="agentTypeAdded">
<arg name="agentType" type="s" direction="out"/>
</signal>
<signal name="agentTypeRemoved">
<arg name="agentType" type="s" direction="out"/>
</signal>
<signal name="agentInstanceAdded">
<arg name="agentIdentifier" type="s" direction="out"/>
</signal>
<signal name="agentInstanceRemoved">
<arg name="agentIdentifier" type="s" direction="out"/>
</signal>
<signal name="agentInstanceStatusChanged">
<arg name="agentIdentifier" type="s" direction="out"/>
<arg name="status" type="i" direction="out"/>
<arg name="message" type="s" direction="out"/>
</signal>
<signal name="agentInstanceAdvancedStatusChanged">
<annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="QVariantMap"/>
<arg name="agentIdentifier" type="s" direction="out"/>
<arg name="status" type="a{sv}" direction="out"/>
</signal>
<signal name="agentInstanceProgressChanged">
<arg name="agentIdentifier" type="s" direction="out"/>
<arg name="progress" type="u" direction="out"/>
<arg name="message" type="s" direction="out"/>
</signal>
<signal name="agentInstanceNameChanged">
<arg name="agentIdentifier" type="s" direction="out"/>
<arg name="name" type="s" direction="out"/>
</signal>
<signal name="agentInstanceWarning">
<arg name="agentIdentifier" type="s" direction="out"/>
<arg name="message" type="s" direction="out"/>
</signal>
<signal name="agentInstanceError">
<arg name="agentIdentifier" type="s" direction="out"/>
<arg name="message" type="s" direction="out"/>
</signal>
<signal name="agentInstanceOnlineChanged">
<arg name="agentIdentifier" type="s" direction="out"/>
<arg name="state" type="b" direction="out"/>
</signal>
<method name="agentTypes">
<arg type="as" direction="out"/>
</method>
<method name="agentName">
<arg type="s" direction="out"/>
<arg name="identifier" type="s" direction="in"/>
</method>
<method name="agentName">
<arg type="s" direction="out"/>
<arg name="identifier" type="s" direction="in"/>
<arg name="language" type="s" direction="in"/>
</method>
<method name="agentComment">
<arg type="s" direction="out"/>
<arg name="identifier" type="s" direction="in"/>
</method>
<method name="agentComment">
<arg type="s" direction="out"/>
<arg name="identifier" type="s" direction="in"/>
<arg name="language" type="s" direction="in"/>
</method>
<method name="agentIcon">
<arg type="s" direction="out"/>
<arg name="identifier" type="s" direction="in"/>
</method>
<method name="agentMimeTypes">
<arg type="as" direction="out"/>
<arg name="identifier" type="s" direction="in"/>
</method>
<method name="agentCapabilities">
<arg type="as" direction="out"/>
<arg name="identifier" type="s" direction="in"/>
</method>
<method name="agentCustomProperties">
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QVariantMap"/>
<arg type="a{sv}" direction="out"/>
<arg name="identifier" type="s" direction="in"/>
</method>
<method name="createAgentInstance">
<arg type="s" direction="out"/>
<arg name="identifier" type="s" direction="in"/>
</method>
<method name="removeAgentInstance">
<arg name="identifier" type="s" direction="in"/>
</method>
<method name="agentInstanceType">
<arg type="s" direction="out"/>
<arg name="identifier" type="s" direction="in"/>
</method>
<method name="agentInstances">
<arg type="as" direction="out"/>
</method>
<method name="agentInstanceStatus">
<arg type="i" direction="out"/>
<arg name="identifier" type="s" direction="in"/>
</method>
<method name="agentInstanceStatusMessage">
<arg type="s" direction="out"/>
<arg name="identifier" type="s" direction="in"/>
</method>
<method name="agentInstanceProgress">
<arg type="u" direction="out"/>
<arg name="identifier" type="s" direction="in"/>
</method>
<method name="agentInstanceProgressMessage">
<arg type="s" direction="out"/>
<arg name="identifier" type="s" direction="in"/>
</method>
<method name="setAgentInstanceName">
<arg name="identifier" type="s" direction="in"/>
<arg name="name" type="s" direction="in"/>
</method>
<method name="agentInstanceName">
<arg type="s" direction="out"/>
<arg name="identifier" type="s" direction="in"/>
</method>
<method name="agentInstanceName">
<arg type="s" direction="out"/>
<arg name="identifier" type="s" direction="in"/>
<arg name="language" type="s" direction="in"/>
</method>
<method name="agentInstanceConfigure">
<arg name="identifier" type="s" direction="in"/>
<arg name="windowId" type="x" direction="in"/>
</method>
<method name="agentInstanceSynchronize">
<arg name="identifier" type="s" direction="in"/>
</method>
<method name="agentInstanceSynchronizeCollectionTree">
<arg name="identifier" type="s" direction="in"/>
</method>
<method name="agentInstanceSynchronizeCollection">
<arg name="identifier" type="s" direction="in"/>
<arg name="collection" type="x" direction="in"/>
</method>
<method name="agentInstanceSynchronizeCollection">
<arg name="identifier" type="s" direction="in"/>
<arg name="collection" type="x" direction="in"/>
<arg name="recursive" type="b" direction="in"/>
</method>
<method name="agentInstanceOnline">
<arg type="b" direction="out"/>
<arg name="identifier" type="s" direction="in"/>
</method>
<method name="setAgentInstanceOnline">
<arg name="identifier" type="s" direction="in"/>
<arg name="state" type="b" direction="in"/>
</method>
<method name="restartAgentInstance">
<arg name="identifier" type="s" direction="in"/>
</method>
</interface>
</node>

View file

@ -0,0 +1,15 @@
<!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.freedesktop.Akonadi.AgentManagerInternal">
<method name="addSearch">
<arg name="query" type="s" direction="in"/>
<arg name="queryLanguage" type="s" direction="in"/>
<arg name="destination" type="x" direction="in"/>
<annotation name="org.freedesktop.DBus.Method.NoReply" value="true"/>
</method>
<method name="removeSearch">
<arg name="destination" type="x" direction="in"/>
<annotation name="org.freedesktop.DBus.Method.NoReply" value="true"/>
</method>
</interface>
</node>

View file

@ -0,0 +1,22 @@
<!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.freedesktop.Akonadi.AgentServer">
<method name="agentInstanceConfigure">
<arg name="identifier" type="s" direction="in" />
<arg name="windowId" type="x" direction="in" />
</method>
<method name="started">
<arg type="b" direction="out"/>
<arg name="identifier" type="s" direction="in"/>
</method>
<method name="startAgent">
<arg name="identifier" type="s" direction="in"/>
<arg name="typeIdentifier" type="s" direction="in"/>
<arg name="fileName" type="s" direction="in"/>
</method>
<method name="stopAgent">
<arg name="identifier" type="s" direction="in"/>
</method>
<method name="quit"/>
</interface>
</node>

View file

@ -0,0 +1,6 @@
<!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.freedesktop.Akonadi.ControlManager">
<method name="shutdown"/>
</interface>
</node>

View file

@ -0,0 +1,34 @@
<!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.freedesktop.Akonadi.NotificationManager">
<signal name="notify">
<arg name="message" type="a(ayiixsayxxsas)" direction="out"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="const Akonadi::NotificationMessage::List &amp;"/>
<!-- In0 annotation for compatibility with qdbusxml2cpp from Qt4.3.0 -->
<annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="const Akonadi::NotificationMessage::List &amp;"/>
</signal>
<method name="subscribe">
<arg type="s" name="identifier" direction="in"/>
<arg type="o" direction="out"/>
</method>
<signal name="subscribed">
<arg type="s" name="identifier" direction="out"/>
</signal>
<method name="subscribeV2">
<arg type="s" name="identifier" direction="in"/>
<arg type="b" name="serverSideMonitor" direction="in"/>
<arg type="o" direction="out"/>
</method>
<method name="unsubscribe">
<arg type="s" name="identifier" direction="in"/>
</method>
<signal name="unsubscribed">
<arg type="s" name="identifier" direction="out"/>
</signal>
<method name="subscribers">
<arg type="as" direction="out" />
</method>
</interface>
</node>

View file

@ -0,0 +1,112 @@
<!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.freedesktop.Akonadi.NotificationSource">
<signal name="notify">
<arg name="message" type="a(ayiixsayxxsas)" direction="out"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="const Akonadi::NotificationMessage::List &amp;"/>
<!-- In0 annotation for compatibility with qdbusxml2cpp from Qt4.3.0 -->
<annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="const Akonadi::NotificationMessage::List &amp;"/>
</signal>
<signal name="notifyV2">
<arg name="message" type="a(ayiia(xsss)ayayxxasaayaay)" direction="out"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="const Akonadi::NotificationMessageV2::List &amp;"/>
<!-- In0 annotation for compatibility with qdbusxml2cpp from Qt4.3.0 -->
<annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="const Akonadi::NotificationMessageV2::List &amp;"/>
</signal>
<signal name="notifyV3">
<arg name="message" type="a(ayiia(xsss)ayayxxasaayaayaiai)" direction="out"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="const Akonadi::NotificationMessageV3::List &amp;"/>
<!-- In0 annotation for compatibility with qdbusxml2cpp from Qt4.3.0 -->
<annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="const Akonadi::NotificationMessageV3::List &amp;"/>
</signal>
<method name="unsubscribe">
</method>
<method name="setMonitoredCollection">
<annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="Akonadi::Entity::Id"/>
<arg name="collection" type="x" direction="in"/>
<arg name="monitored" type="b" direction="in"/>
</method>
<method name="monitoredCollections">
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QVector&lt;qint64&gt;"/>
<arg type="ax" direction="out"/>
</method>
<signal name="monitoredCollectionsChanged" />
<method name="setMonitoredItem">
<annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="Akonadi::Entity::Id"/>
<arg name="item" type="x" direction="in"/>
<arg name="monitored" type="b" direction="in"/>
</method>
<method name="monitoredItems">
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QVector&lt;qint64&gt;"/>
<arg type="ax" direction="out"/>
</method>
<signal name="monitoredItemsChanged" />
<method name="setMonitoredTag">
<annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="Akonadi::Entity::Id"/>
<arg name="tag" type="x" direction="in"/>
<arg name="monitored" type="b" direction="in"/>
</method>
<method name="monitoredTags">
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QVector&lt;qint64&gt;"/>
<arg type="ax" direction="out"/>
</method>
<signal name="monitoredTagsChanged"/>
<method name="setMonitoredType">
<annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="Akonadi::NotificationMessageV2::Type"/>
<arg name="type" type="(i)" direction="in"/>
<arg name="monitored" type="b" direction="in"/>
</method>
<method name="monitoredTypes">
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QVector&lt;Akonadi::NotificationMessageV2::Type&gt;"/>
<arg type="a(i)" direction="out"/>
</method>
<signal name="monitoredTypesChanged"/>
<method name="setMonitoredResource">
<annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="const QByteArray &amp;"/>
<arg name="resource" type="ay" direction="in"/>
<arg name="monitored" type="b" direction="in"/>
</method>
<method name="monitoredResources">
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QVector&lt;QByteArray&gt;"/>
<arg type="aay" direction="out"/>
</method>
<signal name="monitoredResourcesChanged" />
<method name="setMonitoredMimeType">
<annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="const QString &amp;"/>
<arg name="mimetype" type="s" direction="in"/>
<arg name="monitored" type="b" direction="in"/>
</method>
<method name="monitoredMimeTypes">
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="const QStringList &amp;"/>
<arg type="as" direction="out"/>
</method>
<signal name="monitoredMimeTypesChanged" />
<method name="setAllMonitored">
<arg name="allMonitored" type="b" direction="in"/>
</method>
<method name="isAllMonitored">
<arg type="b" direction="out"/>
</method>
<signal name="isAllMonitoredChanged" />
<method name="setIgnoredSession">
<annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="const QByteArray &amp;"/>
<arg name="session" type="ay" direction="in"/>
<arg name="ignored" type="b" direction="in"/>
</method>
<method name="ignoredSessions">
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QVector&lt;QByteArray&gt;"/>
<arg type="aay" direction="out"/>
</method>
<signal name="ignoredSessionsChanged"/>
</interface>
</node>

View file

@ -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.freedesktop.Akonadi.Preprocessor">
<signal name="itemProcessed">
<arg name="id" type="x" direction="out"/>
</signal>
<method name="beginProcessItem">
<arg name="id" type="x" direction="in"/>
<arg name="collectionId" type="x" direction="in"/>
<arg name="mimeType" type="s" direction="in"/>
<annotation name="org.freedesktop.DBus.Method.NoReply" value="true"/>
</method>
</interface>
</node>

View file

@ -0,0 +1,13 @@
<!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.freedesktop.Akonadi.PreprocessorManager">
<method name="registerInstance">
<arg name="id" type="s" direction="in"/>
<annotation name="org.freedesktop.DBus.Method.NoReply" value="true"/>
</method>
<method name="unregisterInstance">
<arg name="id" type="s" direction="in"/>
<annotation name="org.freedesktop.DBus.Method.NoReply" value="true"/>
</method>
</interface>
</node>

View file

@ -0,0 +1,52 @@
<!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.freedesktop.Akonadi.Resource">
<signal name="nameChanged">
<arg name="name" type="s" direction="out"/>
</signal>
<signal name="synchronized"/>
<signal name="attributesSynchronized">
<arg type="x" name="collectionId"/>
</signal>
<signal name="collectionTreeSynchronized"/>
<method name="requestItemDelivery">
<arg type="b" direction="out"/>
<arg name="uid" type="x" direction="in"/>
<arg name="remoteId" type="s" direction="in"/>
<arg name="mimeType" type="s" direction="in"/>
<arg name="parts" type="as" direction="in"/>
</method>
<method name="requestItemDeliveryV2">
<arg type="s" direction="out"/>
<arg name="uid" type="x" direction="in"/>
<arg name="remoteId" type="s" direction="in"/>
<arg name="mimeType" type="s" direction="in"/>
<arg name="parts" type="as" direction="in"/>
</method>
<method name="synchronize">
<annotation name="org.freedesktop.DBus.Method.NoReply" value="true"/>
</method>
<method name="synchronizeCollectionTree">
<annotation name="org.freedesktop.DBus.Method.NoReply" value="true"/>
</method>
<method name="synchronizeCollection">
<arg name="collectionId" type="x" direction="in"/>
<annotation name="org.freedesktop.DBus.Method.NoReply" value="true"/>
</method>
<method name="synchronizeCollection">
<arg name="collectionId" type="x" direction="in"/>
<arg name="recursive" type="b" direction="in"/>
<annotation name="org.freedesktop.DBus.Method.NoReply" value="true"/>
</method>
<method name="synchronizeCollectionAttributes">
<arg name="collectionId" type="x" direction="in"/>
<annotation name="org.freedesktop.DBus.Method.NoReply" value="true"/>
</method>
<method name="setName">
<arg name="name" type="s" direction="in"/>
</method>
<method name="name">
<arg type="s" direction="out"/>
</method>
</interface>
</node>

View file

@ -0,0 +1,15 @@
<!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.freedesktop.Akonadi.ResourceManager">
<method name="addResourceInstance">
<arg name="identifier" type="s" direction="in"/>
<arg name="capabilities" type="as" direction="in"/>
</method>
<method name="removeResourceInstance">
<arg name="identifier" type="s" direction="in"/>
</method>
<method name="resourceInstances">
<arg type="as" direction="out"/>
</method>
</interface>
</node>

View file

@ -0,0 +1,13 @@
<!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.freedesktop.Akonadi.SearchManager">
<method name="registerInstance">
<arg name="id" type="s" direction="in"/>
<annotation name="org.freedesktop.DBus.Method.NoReply" value="true"/>
</method>
<method name="unregisterInstance">
<arg name="id" type="s" direction="in"/>
<annotation name="org.freedesktop.DBus.Method.NoReply" value="true"/>
</method>
</interface>
</node>

View file

@ -0,0 +1,6 @@
<!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.freedesktop.Akonadi.Server">
<method name="quit"/>
</interface>
</node>

View file

@ -0,0 +1,24 @@
<!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.freedesktop.Akonadi.StorageDebugger">
<method name="enableSQLDebugging">
<arg type="b" name="enable" direction="in" />
</method>
<method name="isSQLDebuggingEnabled">
<arg type="b" direction="out" />
</method>
<signal name="queryExecuted">
<arg type="d" name="sequence" direction="out" />
<arg type="u" name="duration" direction="out" />
<arg type="s" name="query" direction="out" />
<annotation name="org.qtproject.QtDBus.QtTypeName.In3" value="const QMap&lt;QString,QVariant&gt; &amp;"/>
<arg type="{sv}" name="values" direction="out" />
<arg type="i" name="resultsCount" direction="out"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.In5" value="const QList&lt;QList&lt;QVariant&gt; &gt; &amp;"/>
<arg type="aav" name="result" direction="out" />
<arg type="s" name="error" direction="out"/>
</signal>
</interface>
</node>

View file

@ -0,0 +1,17 @@
<!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.freedesktop.Akonadi.Tracer">
<method name="signal">
<arg name="signalName" type="s" direction="in"/>
<arg name="msg" type="s" direction="in"/>
</method>
<method name="warning">
<arg name="componentName" type="s" direction="in"/>
<arg name="msg" type="s" direction="in"/>
</method>
<method name="error">
<arg name="componentName" type="s" direction="in"/>
<arg name="msg" type="s" direction="in"/>
</method>
</interface>
</node>

View file

@ -0,0 +1,33 @@
<!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.freedesktop.Akonadi.TracerNotification">
<signal name="connectionStarted">
<arg name="identifier" type="s" direction="out"/>
<arg name="msg" type="s" direction="out"/>
</signal>
<signal name="connectionEnded">
<arg name="identifier" type="s" direction="out"/>
<arg name="msg" type="s" direction="out"/>
</signal>
<signal name="connectionDataInput">
<arg name="identifier" type="s" direction="out"/>
<arg name="msg" type="s" direction="out"/>
</signal>
<signal name="connectionDataOutput">
<arg name="identifier" type="s" direction="out"/>
<arg name="msg" type="s" direction="out"/>
</signal>
<signal name="signalEmitted">
<arg name="signalName" type="s" direction="out"/>
<arg name="msg" type="s" direction="out"/>
</signal>
<signal name="warningEmitted">
<arg name="componentName" type="s" direction="out"/>
<arg name="msg" type="s" direction="out"/>
</signal>
<signal name="errorEmitted">
<arg name="componentName" type="s" direction="out"/>
<arg name="msg" type="s" direction="out"/>
</signal>
</interface>
</node>

504
akonadi/lgpl-license Normal file
View file

@ -0,0 +1,504 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 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!

View file

@ -0,0 +1,40 @@
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${_ENABLE_EXCEPTIONS}")
configure_file(akonadiprotocolinternals_export.h.in ${Akonadi_BINARY_DIR}/akonadiprotocolinternals_export.h)
# libakonadiprotocolinternals
set(akonadiprotocolinternals_srcs
imapparser.cpp
imapset.cpp
notificationmessage.cpp
notificationmessagev2.cpp
notificationmessagev3.cpp
xdgbasedirs.cpp
)
add_library(akonadiprotocolinternals ${LIBRARY_TYPE} ${akonadiprotocolinternals_srcs})
target_link_libraries(akonadiprotocolinternals ${QT_QTCORE_LIBRARY} ${QT_QTDBUS_LIBRARY})
set_target_properties(akonadiprotocolinternals PROPERTIES
VERSION ${AKONADI_VERSION}
SOVERSION ${AKONADI_SOVERSION}
DEFINE_SYMBOL MAKE_AKONADIPROTOCOLINTERNALS_LIB
)
install(TARGETS akonadiprotocolinternals EXPORT akonadiLibraryTargets ${INSTALL_TARGETS_DEFAULT_ARGS})
install(FILES
${Akonadi_BINARY_DIR}/akonadiprotocolinternals_export.h
imapparser_p.h
imapset_p.h
notificationmessage_p.h
notificationmessagev2_p.h
notificationmessagev3_p.h
protocol_p.h
xdgbasedirs_p.h
capabilities_p.h
DESTINATION ${INCLUDE_INSTALL_DIR}/akonadi/private
)
add_subdirectory(tests)

View file

@ -0,0 +1,40 @@
/* This file is part of the KDE project
Copyright (C) 2007 David Faure <faure@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#ifndef AKONADIPROTOCOLINTERNALS_EXPORT_H
#define AKONADIPROTOCOLINTERNALS_EXPORT_H
#include <QtCore/QtGlobal>
#cmakedefine AKONADI_STATIC_LIBS
#ifndef AKONADIPROTOCOLINTERNALS_EXPORT
# if defined(AKONADI_STATIC_LIBS)
/* No export/import for static libraries */
# define AKONADIPROTOCOLINTERNALS_EXPORT
# elif defined(MAKE_AKONADIPROTOCOLINTERNALS_LIB)
/* We are building this library */
# define AKONADIPROTOCOLINTERNALS_EXPORT Q_DECL_EXPORT
# else
/* We are using this library */
# define AKONADIPROTOCOLINTERNALS_EXPORT Q_DECL_IMPORT
# endif
#endif
#endif

View file

@ -0,0 +1,37 @@
/*
Copyright (c) 2009 Volker Krause <vkrause@kde.org>
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
*/
#ifndef AKONADI_CAPABILITIES_P_H
#define AKONADI_CAPABILITIES_P_H
/**
@file capabilites_p.h Shared constants for agent capabilities.
@todo Fill this file with the missing capabilities.
*/
#define AKONADI_AGENT_CAPABILITY_AUTOSTART "Autostart"
#define AKONADI_AGENT_CAPABILITY_NOCONFIG "NoConfig"
#define AKONADI_AGENT_CAPABILITY_PREPROCESSOR "Preprocessor"
#define AKONADI_AGENT_CAPABILITY_RESOURCE "Resource"
#define AKONADI_AGENT_CAPABILITY_SEARCH "Search"
#define AKONADI_AGENT_CAPABILITY_UNIQUE "Unique"
#define AKONADI_AGENT_CAPABILITY_VIRTUAL "Virtual"
#endif

698
akonadi/libs/imapparser.cpp Normal file
View file

@ -0,0 +1,698 @@
/*
Copyright (c) 2006 - 2007 Volker Krause <vkrause@kde.org>
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
*/
#include "imapparser_p.h"
#include <QtCore/QDateTime>
#include <QtCore/QDebug>
#include <ctype.h>
using namespace Akonadi;
class ImapParser::Private
{
public:
QByteArray tagBuffer;
QByteArray dataBuffer;
int parenthesesCount;
qint64 literalSize;
bool continuation;
// returns true if readBuffer contains a literal start and sets
// parser state accordingly
bool checkLiteralStart( const QByteArray &readBuffer, int pos = 0 )
{
if ( readBuffer.trimmed().endsWith( '}' ) ) {
const int begin = readBuffer.lastIndexOf( '{' );
const int end = readBuffer.lastIndexOf( '}' );
// new literal in previous literal data block
if ( begin < pos ) {
return false;
}
// TODO error handling
literalSize = readBuffer.mid( begin + 1, end - begin - 1 ).toLongLong();
// empty literal
if ( literalSize == 0 ) {
return false;
}
continuation = true;
dataBuffer.reserve( dataBuffer.size() + literalSize + 1 );
return true;
}
return false;
}
};
namespace {
template <typename T>
int parseParenthesizedListHelper( const QByteArray &data, T &result, int start )
{
result.clear();
if ( start >= data.length() ) {
return data.length();
}
const int begin = data.indexOf( '(', start );
if ( begin < 0 ) {
return start;
}
int count = 0;
int sublistBegin = start;
bool insideQuote = false;
for ( int i = begin + 1; i < data.length(); ++i ) {
const char currentChar = data[i];
if ( currentChar == '(' && !insideQuote ) {
++count;
if ( count == 1 ) {
sublistBegin = i;
}
continue;
}
if ( currentChar == ')' && !insideQuote ) {
if ( count <= 0 ) {
return i + 1;
}
if ( count == 1 ) {
result.append( data.mid( sublistBegin, i - sublistBegin + 1 ) );
}
--count;
continue;
}
if ( currentChar == ' ' || currentChar == '\n' || currentChar == '\r' ) {
continue;
}
if ( count == 0 ) {
QByteArray ba;
const int consumed = ImapParser::parseString( data, ba, i );
i = consumed - 1; // compensate for the for loop increment
result.append( ba );
} else if ( count > 0 ) {
if ( currentChar == '"' ) {
insideQuote = !insideQuote;
} else if ( currentChar == '\\' && insideQuote ) {
++i;
continue;
}
}
}
return data.length();
}
}
int ImapParser::parseParenthesizedList( const QByteArray &data, QVarLengthArray<QByteArray,16> &result, int start )
{
return parseParenthesizedListHelper( data, result, start );
}
int ImapParser::parseParenthesizedList( const QByteArray &data, QList<QByteArray> &result, int start )
{
return parseParenthesizedListHelper( data, result, start );
}
int ImapParser::parseString( const QByteArray &data, QByteArray &result, int start )
{
int begin = stripLeadingSpaces( data, start );
result.clear();
if ( begin >= data.length() ) {
return data.length();
}
// literal string
// TODO: error handling
if ( data[begin] == '{' ) {
int end = data.indexOf( '}', begin );
Q_ASSERT( end > begin );
int size = data.mid( begin + 1, end - begin - 1 ).toInt();
// strip CRLF
begin = end + 1;
if ( begin < data.length() && data[begin] == '\r' ) {
++begin;
}
if ( begin < data.length() && data[begin] == '\n' ) {
++begin;
}
end = begin + size;
result = data.mid( begin, end - begin );
return end;
}
// quoted string
return parseQuotedString( data, result, begin );
}
int ImapParser::parseQuotedString( const QByteArray &data, QByteArray &result, int start )
{
int begin = stripLeadingSpaces( data, start );
int end = begin;
result.clear();
if ( begin >= data.length() ) {
return data.length();
}
bool foundSlash = false;
// quoted string
if ( data[begin] == '"' ) {
++begin;
for ( int i = begin; i < data.length(); ++i ) {
const char ch = data.at( i );
if ( foundSlash ) {
foundSlash = false;
if ( ch == 'r' ) {
result += '\r';
} else if ( ch == 'n' ) {
result += '\n';
} else if ( ch == '\\' ) {
result += '\\';
} else if ( ch == '\"' ) {
result += '\"';
} else {
//TODO: this is actually an error
result += ch;
}
continue;
}
if ( ch == '\\' ) {
foundSlash = true;
continue;
}
if ( ch == '"' ) {
end = i + 1; // skip the '"'
break;
}
result += ch;
}
}
// unquoted string
else {
bool reachedInputEnd = true;
for ( int i = begin; i < data.length(); ++i ) {
const char ch = data.at( i );
if ( ch == ' ' || ch == '(' || ch == ')' || ch == '\n' || ch == '\r' ) {
end = i;
reachedInputEnd = false;
break;
}
if ( ch == '\\' ) {
foundSlash = true;
}
}
if ( reachedInputEnd ) {
end = data.length();
}
result = data.mid( begin, end - begin );
// transform unquoted NIL
if ( result == "NIL" ) {
result.clear();
}
// strip quotes
if ( foundSlash ) {
while ( result.contains( "\\\"" ) ) {
result.replace( "\\\"", "\"" );
}
while ( result.contains( "\\\\" ) ) {
result.replace( "\\\\", "\\" );
}
}
}
return end;
}
int ImapParser::stripLeadingSpaces( const QByteArray &data, int start )
{
for ( int i = start; i < data.length(); ++i ) {
if ( data[i] != ' ' ) {
return i;
}
}
return data.length();
}
int ImapParser::parenthesesBalance( const QByteArray &data, int start )
{
int count = 0;
bool insideQuote = false;
for ( int i = start; i < data.length(); ++i ) {
const char ch = data[i];
if ( ch == '"' ) {
insideQuote = !insideQuote;
continue;
}
if ( ch == '\\' && insideQuote ) {
++i;
continue;
}
if ( ch == '(' && !insideQuote ) {
++count;
continue;
}
if ( ch == ')' && !insideQuote ) {
--count;
continue;
}
}
return count;
}
QByteArray ImapParser::join( const QList<QByteArray> &list, const QByteArray &separator )
{
// shortcuts for the easy cases
if ( list.isEmpty() ) {
return QByteArray();
}
if ( list.size() == 1 ) {
return list.first();
}
// avoid expensive realloc's by determining the size beforehand
QList<QByteArray>::const_iterator it = list.constBegin();
const QList<QByteArray>::const_iterator endIt = list.constEnd();
int resultSize = ( list.size() - 1 ) * separator.size();
for ( ; it != endIt; ++it ) {
resultSize += ( *it ).size();
}
QByteArray result;
result.reserve( resultSize );
it = list.constBegin();
result += ( *it );
++it;
for ( ; it != endIt; ++it ) {
result += separator;
result += ( *it );
}
return result;
}
QByteArray ImapParser::join( const QSet<QByteArray> &set, const QByteArray &separator )
{
const QList<QByteArray> list = QList<QByteArray>::fromSet( set );
return ImapParser::join( list, separator );
}
int ImapParser::parseString( const QByteArray &data, QString &result, int start )
{
QByteArray tmp;
const int end = parseString( data, tmp, start );
result = QString::fromUtf8( tmp );
return end;
}
int ImapParser::parseNumber( const QByteArray &data, qint64 &result, bool *ok, int start )
{
if ( ok ) {
*ok = false;
}
int pos = stripLeadingSpaces( data, start );
if ( pos >= data.length() ) {
return data.length();
}
int begin = pos;
for ( ; pos < data.length(); ++pos ) {
if ( !isdigit( data.at( pos ) ) ) {
break;
}
}
const QByteArray tmp = data.mid( begin, pos - begin );
result = tmp.toLongLong( ok );
return pos;
}
QByteArray ImapParser::quote( const QByteArray &data )
{
if ( data.isEmpty() ) {
return QByteArray( "\"\"" );
}
const int inputLength = data.length();
int stuffToQuote = 0;
for ( int i = 0; i < inputLength; ++i ) {
const char ch = data.at( i );
if ( ch == '"' || ch == '\\' || ch == '\n' || ch == '\r' ) {
++stuffToQuote;
}
}
QByteArray result;
result.reserve( inputLength + stuffToQuote + 2 );
result += '"';
// shortcut for the case that we don't need to quote anything at all
if ( stuffToQuote == 0 ) {
result += data;
} else {
for ( int i = 0; i < inputLength; ++i ) {
const char ch = data.at( i );
if ( ch == '\n' ) {
result += "\\n";
continue;
}
if ( ch == '\r' ) {
result += "\\r";
continue;
}
if ( ch == '"' || ch == '\\' ) {
result += '\\';
}
result += ch;
}
}
result += '"';
return result;
}
int ImapParser::parseSequenceSet( const QByteArray &data, ImapSet &result, int start )
{
int begin = stripLeadingSpaces( data, start );
qint64 value = -1, lower = -1, upper = -1;
for ( int i = begin; i < data.length(); ++i ) {
if ( data[i] == '*' ) {
value = 0;
} else if ( data[i] == ':' ) {
lower = value;
} else if ( isdigit( data[i] ) ) {
bool ok = false;
i = parseNumber( data, value, &ok, i );
Q_ASSERT( ok ); // TODO handle error
--i;
} else {
upper = value;
if ( lower < 0 ) {
lower = value;
}
result.add( ImapInterval( lower, upper ) );
lower = -1;
upper = -1;
value = -1;
if ( data[i] != ',' ) {
return i;
}
}
}
// take care of left-overs at input end
upper = value;
if ( lower < 0 ) {
lower = value;
}
if ( lower >= 0 && upper >= 0 ) {
result.add( ImapInterval( lower, upper ) );
}
return data.length();
}
int ImapParser::parseDateTime( const QByteArray &data, QDateTime &dateTime, int start )
{
// Syntax:
// date-time = DQUOTE date-day-fixed "-" date-month "-" date-year
// SP time SP zone DQUOTE
// date-day-fixed = (SP DIGIT) / 2DIGIT
// ; Fixed-format version of date-day
// date-month = "Jan" / "Feb" / "Mar" / "Apr" / "May" / "Jun" /
// "Jul" / "Aug" / "Sep" / "Oct" / "Nov" / "Dec"
// date-year = 4DIGIT
// time = 2DIGIT ":" 2DIGIT ":" 2DIGIT
// ; Hours minutes seconds
// zone = ("+" / "-") 4DIGIT
// ; Signed four-digit value of hhmm representing
// ; hours and minutes east of Greenwich (that is,
// ; the amount that the given time differs from
// ; Universal Time). Subtracting the timezone
// ; from the given time will give the UT form.
// ; The Universal Time zone is "+0000".
// Example : "28-May-2006 01:03:35 +0200"
// Position: 0123456789012345678901234567
// 1 2
int pos = stripLeadingSpaces( data, start );
if ( data.length() <= pos ) {
return pos;
}
bool quoted = false;
if ( data[pos] == '"' ) {
quoted = true;
++pos;
if ( data.length() <= pos + 26 ) {
return start;
}
} else {
if ( data.length() < pos + 26 ) {
return start;
}
}
bool ok = true;
const int day = ( data[pos] == ' ' ? data[pos + 1] - '0' // single digit day
: data.mid( pos, 2 ).toInt( &ok ) );
if ( !ok ) {
return start;
}
pos += 3;
const QByteArray shortMonthNames( "janfebmaraprmayjunjulaugsepoctnovdec" );
int month = shortMonthNames.indexOf( data.mid( pos, 3 ).toLower() );
if ( month == -1 ) {
return start;
}
month = month / 3 + 1;
pos += 4;
const int year = data.mid( pos, 4 ).toInt( &ok );
if ( !ok ) {
return start;
}
pos += 5;
const int hours = data.mid( pos, 2 ).toInt( &ok );
if ( !ok ) {
return start;
}
pos += 3;
const int minutes = data.mid( pos, 2 ).toInt( &ok );
if ( !ok ) {
return start;
}
pos += 3;
const int seconds = data.mid( pos, 2 ).toInt( &ok );
if ( !ok ) {
return start;
}
pos += 4;
const int tzhh = data.mid( pos, 2 ).toInt( &ok );
if ( !ok ) {
return start;
}
pos += 2;
const int tzmm = data.mid( pos, 2 ).toInt( &ok );
if ( !ok ) {
return start;
}
int tzsecs = tzhh * 60 * 60 + tzmm * 60;
if ( data[pos - 3] == '-' ) {
tzsecs = -tzsecs;
}
const QDate date( year, month, day );
const QTime time( hours, minutes, seconds );
dateTime = QDateTime( date, time, Qt::UTC );
if ( !dateTime.isValid() ) {
return start;
}
dateTime = dateTime.addSecs( -tzsecs );
pos += 2;
if ( data.length() <= pos || !quoted ) {
return pos;
}
if ( data[pos] == '"' ) {
++pos;
}
return pos;
}
void ImapParser::splitVersionedKey( const QByteArray &data, QByteArray &key, int &version )
{
if ( data.contains( '[' ) && data.contains( ']' ) ) {
const int startPos = data.indexOf( '[' );
const int endPos = data.indexOf( ']' );
if ( startPos != -1 && endPos != -1 && endPos > startPos ) {
bool ok = false;
version = data.mid( startPos + 1, endPos - startPos - 1 ).toInt( &ok );
if ( !ok ) {
version = 0;
}
key = data.left( startPos );
}
} else {
key = data;
version = 0;
}
}
ImapParser::ImapParser()
: d ( new Private )
{
reset();
}
ImapParser::~ImapParser()
{
delete d;
}
bool ImapParser::parseNextLine( const QByteArray &readBuffer )
{
d->continuation = false;
// first line, get the tag
if ( d->tagBuffer.isEmpty() ) {
const int startOfData = ImapParser::parseString( readBuffer, d->tagBuffer );
if ( startOfData < readBuffer.length() && startOfData >= 0 ) {
d->dataBuffer = readBuffer.mid( startOfData + 1 );
}
} else {
d->dataBuffer += readBuffer;
}
// literal read in progress
if ( d->literalSize > 0 ) {
d->literalSize -= readBuffer.size();
// still not everything read
if ( d->literalSize > 0 ) {
return false;
}
// check the remaining (non-literal) part for parentheses
if ( d->literalSize < 0 ) {
// the following looks strange but works since literalSize can be negative here
d->parenthesesCount += ImapParser::parenthesesBalance( readBuffer, readBuffer.length() + d->literalSize );
// check if another literal read was started
if ( d->checkLiteralStart( readBuffer, readBuffer.length() + d->literalSize ) ) {
return false;
}
}
// literal string finished but still open parentheses
if ( d->parenthesesCount > 0 ) {
return false;
}
} else {
// open parentheses
d->parenthesesCount += ImapParser::parenthesesBalance( readBuffer );
// start new literal read
if ( d->checkLiteralStart( readBuffer ) ) {
return false;
}
// still open parentheses
if ( d->parenthesesCount > 0 ) {
return false;
}
// just a normal response, fall through
}
return true;
}
void ImapParser::parseBlock( const QByteArray &data )
{
Q_ASSERT( d->literalSize >= data.size() );
d->literalSize -= data.size();
d->dataBuffer += data;
}
QByteArray ImapParser::tag() const
{
return d->tagBuffer;
}
QByteArray ImapParser::data() const
{
return d->dataBuffer;
}
void ImapParser::reset()
{
d->dataBuffer.clear();
d->tagBuffer.clear();
d->parenthesesCount = 0;
d->literalSize = 0;
d->continuation = false;
}
bool ImapParser::continuationStarted() const
{
return d->continuation;
}
qint64 ImapParser::continuationSize() const
{
return d->literalSize;
}

211
akonadi/libs/imapparser_p.h Normal file
View file

@ -0,0 +1,211 @@
/*
Copyright (c) 2006 - 2007 Volker Krause <vkrause@kde.org>
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
*/
#ifndef AKONADI_IMAPPARSER_P_H
#define AKONADI_IMAPPARSER_P_H
#include "akonadiprotocolinternals_export.h"
#include "imapset_p.h"
#include <QtCore/QByteArray>
#include <QtCore/QList>
#include <QtCore/QVarLengthArray>
namespace Akonadi {
/**
Parser for IMAP messages.
*/
class AKONADIPROTOCOLINTERNALS_EXPORT ImapParser
{
public:
/**
Parses the next parenthesized list in @p data starting from @p start
and puts the result into @p result. The number of used characters is
returned.
This does not recurse into sub-lists.
@param data Source data.
@param result The parsed list.
@param start Start parsing at this index.
*/
static int parseParenthesizedList( const QByteArray &data, QList<QByteArray> &result, int start = 0 );
static int parseParenthesizedList( const QByteArray &data, QVarLengthArray<QByteArray,16> &result, int start = 0 );
/**
Parse the next string in @p data (quoted or literal) starting from @p start
and puts the result into @p result. The number of used characters is returned
(this is not equal to result.length()!).
@param data Source data.
@param result Parsed string, quotation, literal marker, etc. are removed,
'NIL' is transformed into an empty QByteArray.
@param start start parsing at this index.
*/
static int parseString( const QByteArray &data, QByteArray &result, int start = 0 );
/**
Parses the next quoted string from @p data starting at @p start and puts it into
@p result. The number of parsed characters is returned (this is not equal to result.length()!).
@param data Source data.
@param result Parsed string, quotation is removed and 'NIL' is transformed to an empty QByteArray.
@param start Start parsing at this index.
*/
static int parseQuotedString( const QByteArray &data, QByteArray &result, int start = 0 );
/**
Returns the number of leading espaces in @p data starting from @p start.
@param data The source data.
@param start Start parsing at this index.
*/
static int stripLeadingSpaces( const QByteArray &data, int start = 0 );
/**
Returns the parentheses balance for the given data, considering quotes.
@param data The source data.
@param start Start parsing at this index.
*/
static int parenthesesBalance( const QByteArray &data, int start = 0 );
/**
Joins a QByteArray list with the given separator.
@param list The QByteArray list to join.
@param separator The separator.
*/
static QByteArray join( const QList<QByteArray> &list, const QByteArray &separator );
/**
Joins a QByteArray set with the given separator.
@param set The QByteArray set to join.
@param separator The separator.
*/
static QByteArray join( const QSet<QByteArray> &set, const QByteArray &separator );
/**
Same as parseString(), but with additional UTF-8 decoding of the result.
@param data Source data.
@param result Parsed string, quotation, literal marker, etc. are removed,
'NIL' is transformed into an empty QString. UTF-8 decoding is applied..
@param start Start parsing at this index.
*/
static int parseString( const QByteArray &data, QString &result, int start = 0 );
/**
Parses the next integer number from @p data starting at start and puts it into
@p result. The number of characters parsed is returned (this is not the parsed result!).
@param data Source data.
@param result Parsed integer number, invalid if ok is false.
@param ok Set to false if the parsing failed.
@param start Start parsing at this index.
*/
static int parseNumber( const QByteArray &data, qint64 &result, bool *ok = 0, int start = 0 );
/**
Quotes the given QByteArray.
@param data Source data.
*/
static QByteArray quote( const QByteArray &data );
/**
Parse an IMAP sequence set.
@param data source data.
@param result The parse sequence set.
@param start start parsing at this index.
@return end position of parsing.
*/
static int parseSequenceSet( const QByteArray &data, ImapSet &result, int start = 0 );
/**
Parse an IMAP date/time value.
@param data source data.
@param dateTime The result date/time.
@param start Start parsing at this index.
@return end position of parsing.
*/
static int parseDateTime( const QByteArray &data, QDateTime &dateTime, int start = 0 );
/**
Split a versioned key of the form 'key[version]' into its components.
@param data The versioned key.
@param key The unversioned key.
@param version The version of the key or 0 if no version was set.
*/
static void splitVersionedKey( const QByteArray &data, QByteArray &key, int &version );
/**
Constructs a new IMAP parser.
*/
ImapParser();
/**
Destroys an IMAP parser.
*/
~ImapParser();
/**
Parses the given line.
@returns True if an IMAP message was parsed completely, false if more data is needed.
@todo read from a QIODevice directly to avoid an extra line buffer
*/
bool parseNextLine( const QByteArray &readBuffer );
/**
Parses the given block of data.
Note: This currently only handles continuation blocks.
@param data The data to parse.
*/
void parseBlock( const QByteArray &data );
/**
Returns the tag of the parsed message.
Only valid if parseNextLine() returned true.
*/
QByteArray tag() const;
/**
Return the raw data of the parsed IMAP message.
Only valid if parseNextLine() returned true.
*/
QByteArray data() const;
/**
Resets the internal state of the parser. Call before parsing
a new IMAP message.
*/
void reset();
/**
Returns true if the last parsed line contained a literal continuation,
ie. readiness for receiving literal data needs to be indicated.
*/
bool continuationStarted() const;
/**
Returns the expected size of liteal data.
*/
qint64 continuationSize() const;
private:
Q_DISABLE_COPY( ImapParser )
class Private;
Private *const d;
};
}
#endif

270
akonadi/libs/imapset.cpp Normal file
View file

@ -0,0 +1,270 @@
/*
Copyright (c) 2007 Volker Krause <vkrause@kde.org>
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
*/
#include "imapset_p.h"
#include "imapparser_p.h"
#include <QtCore/QSharedData>
#include <limits>
using namespace Akonadi;
class ImapInterval::Private : public QSharedData
{
public:
Private()
: QSharedData()
, begin( 0 )
, end( 0 )
{
}
Private( const Private &other )
: QSharedData( other )
{
begin = other.begin;
end = other.end;
}
Id begin;
Id end;
};
class ImapSet::Private : public QSharedData
{
public:
Private()
: QSharedData()
{
}
Private( const Private &other )
: QSharedData( other )
{
intervals = other.intervals;
}
ImapInterval::List intervals;
};
ImapInterval::ImapInterval()
: d( new Private )
{
}
ImapInterval::ImapInterval( const ImapInterval &other )
: d( other.d )
{
}
ImapInterval::ImapInterval( Id begin, Id end )
: d( new Private )
{
d->begin = begin;
d->end = end;
}
ImapInterval::~ImapInterval()
{
}
ImapInterval &ImapInterval::operator=( const ImapInterval &other )
{
if ( this != &other ) {
d = other.d;
}
return *this;
}
bool ImapInterval::operator==( const ImapInterval &other ) const
{
return ( d->begin == other.d->begin && d->end == other.d->end );
}
ImapInterval::Id ImapInterval::size() const
{
if ( !d->begin && !d->end ) {
return 0;
}
return ( d->end - d->begin + 1 );
}
bool ImapInterval::hasDefinedBegin() const
{
return ( d->begin != 0 );
}
ImapInterval::Id ImapInterval::begin() const
{
return d->begin;
}
bool ImapInterval::hasDefinedEnd() const
{
return ( d->end != 0 );
}
ImapInterval::Id ImapInterval::end() const
{
if ( hasDefinedEnd() ) {
return d->end;
}
return std::numeric_limits<Id>::max();
}
void ImapInterval::setBegin( Id value )
{
Q_ASSERT( value >= 0 );
Q_ASSERT( value <= d->end || !hasDefinedEnd() );
d->begin = value;
}
void ImapInterval::setEnd( Id value )
{
Q_ASSERT( value >= 0 );
Q_ASSERT( value >= d->begin || !hasDefinedBegin() );
d->end = value;
}
QByteArray Akonadi::ImapInterval::toImapSequence() const
{
if ( size() == 0 ) {
return QByteArray();
}
if ( size() == 1 ) {
return QByteArray::number( d->begin );
}
QByteArray rv;
rv += QByteArray::number( d->begin ) + ':';
if ( hasDefinedEnd() ) {
rv += QByteArray::number( d->end );
} else {
rv += '*';
}
return rv;
}
ImapSet::ImapSet()
: d( new Private )
{
}
ImapSet::ImapSet( const ImapSet &other )
: d( other.d )
{
}
ImapSet::~ImapSet()
{
}
ImapSet &ImapSet::operator=( const ImapSet &other )
{
if ( this != &other ) {
d = other.d;
}
return *this;
}
void ImapSet::add( const QList<Id> &values )
{
add( values.toVector() );
}
void ImapSet::add( const QVector<Id> &values )
{
QVector<Id> vals = values;
qSort( vals );
for ( int i = 0; i < vals.count(); ++i ) {
const int begin = vals[i];
Q_ASSERT( begin >= 0 );
if ( i == vals.count() - 1 ) {
d->intervals << ImapInterval( begin, begin );
break;
}
do {
++i;
Q_ASSERT( vals[i] >= 0 );
if ( vals[i] != ( vals[i - 1] + 1 ) ) {
--i;
break;
}
} while ( i < vals.count() - 1 );
d->intervals << ImapInterval( begin, vals[i] );
}
}
void ImapSet::add( const QSet<Id> &values )
{
QVector<Id> v;
v.reserve( values.size() );
for ( QSet<Id>::ConstIterator iter = values.constBegin(); iter != values.constEnd(); ++iter ) {
v.push_back( *iter );
}
add( v );
}
void ImapSet::add( const ImapInterval &interval )
{
d->intervals << interval;
}
QByteArray ImapSet::toImapSequenceSet() const
{
QList<QByteArray> rv;
Q_FOREACH ( const ImapInterval &interval, d->intervals ) {
rv << interval.toImapSequence();
}
return ImapParser::join( rv, "," );
}
ImapInterval::List ImapSet::intervals() const
{
return d->intervals;
}
bool ImapSet::isEmpty() const
{
return d->intervals.isEmpty();
}
QDebug &operator<<( QDebug &d, const Akonadi::ImapInterval &interval )
{
d << interval.toImapSequence();
return d;
}
QDebug operator<<( QDebug d, const Akonadi::ImapSet &set )
{
d << set.toImapSequenceSet();
return d;
}

220
akonadi/libs/imapset_p.h Normal file
View file

@ -0,0 +1,220 @@
/*
Copyright (c) 2007 Volker Krause <vkrause@kde.org>
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
*/
#ifndef AKONADI_IMAPSET_P_H
#define AKONADI_IMAPSET_P_H
#include "akonadiprotocolinternals_export.h"
#include <QtCore/QByteArray>
#include <QtCore/QDebug>
#include <QtCore/QList>
#include <QtCore/QMetaType>
#include <QtCore/QSharedDataPointer>
namespace Akonadi {
/**
Represents a single interval in an ImapSet.
This class is implicitly shared.
*/
class AKONADIPROTOCOLINTERNALS_EXPORT ImapInterval
{
public:
/**
* Describes the ids stored in the interval.
*/
typedef qint64 Id;
/**
A list of ImapInterval objects.
*/
typedef QList<ImapInterval> List;
/**
Constructs an interval that covers all positive numbers.
*/
ImapInterval();
/**
Copy constructor.
*/
ImapInterval( const ImapInterval &other );
/**
Create a new interval.
@param begin The begin of the interval.
@param end Keep default (0) to just set the interval begin
*/
explicit ImapInterval( Id begin, Id end = 0 );
/**
Destructor.
*/
~ImapInterval();
/**
Assignment operator.
*/
ImapInterval &operator=( const ImapInterval &other );
/**
Comparison operator.
*/
bool operator==( const ImapInterval &other ) const;
/**
Returns the size of this interval.
Size is only defined for finite intervals.
*/
Id size() const;
/**
Returns true if this interval has a defined begin.
*/
bool hasDefinedBegin() const;
/**
Returns the begin of this interval. The value is the smallest value part of the interval.
Only valid if begin is defined.
*/
Id begin() const;
/**
Returns true if this intercal has been defined.
*/
bool hasDefinedEnd() const;
/**
Returns the end of this interval. This value is the largest value part of the interval.
Only valid if hasDefinedEnd() returned true.
*/
Id end() const;
/**
Sets the begin of the interval.
*/
void setBegin( Id value );
/**
Sets the end of this interval.
*/
void setEnd( Id value );
/**
Converts this set into an IMAP compatible sequence.
*/
QByteArray toImapSequence() const;
private:
class Private;
QSharedDataPointer<Private> d;
};
/**
Represents a set of natural numbers (1->\f$\infty\f$) in a as compact as possible form.
Used to address Akonadi items via the IMAP protocol or in the database.
This class is implicitly shared.
*/
class AKONADIPROTOCOLINTERNALS_EXPORT ImapSet
{
public:
/**
* Describes the ids stored in the set.
*/
typedef qint64 Id;
/**
Constructs an empty set.
*/
ImapSet();
/**
Copy constructor.
*/
ImapSet( const ImapSet &other );
/**
Destructor.
*/
~ImapSet();
/**
Assignment operator.
*/
ImapSet &operator=( const ImapSet &other );
/**
Adds the given list of positive integer numbers to the set.
The list is sorted and split into as large as possible intervals.
No interval merging is performed.
@param values List of positive integer numbers in arbitrary order
*/
void add( const QVector<Id> &values );
/**
@overload
@deprecated Use the QVector version instead.
*/
void add( const QList<Id> &values );
/**
* @overload
*/
void add( const QSet<Id> &values );
/**
Adds the given ImapInterval to this set.
No interval merging is performed.
*/
void add( const ImapInterval &interval );
/**
Returns a IMAP-compatible QByteArray representation of this set.
*/
QByteArray toImapSequenceSet() const;
/**
Returns the intervals this set consists of.
*/
ImapInterval::List intervals() const;
/**
Returns true if this set doesn't contains any values.
*/
bool isEmpty() const;
private:
class Private;
QSharedDataPointer<Private> d;
};
}
AKONADIPROTOCOLINTERNALS_EXPORT QDebug &operator<<( QDebug &d, const Akonadi::ImapInterval &interval );
AKONADIPROTOCOLINTERNALS_EXPORT QDebug operator<<( QDebug d, const Akonadi::ImapSet &set );
Q_DECLARE_TYPEINFO( Akonadi::ImapInterval, Q_MOVABLE_TYPE );
Q_DECLARE_TYPEINFO( Akonadi::ImapSet, Q_MOVABLE_TYPE );
Q_DECLARE_METATYPE( Akonadi::ImapInterval )
Q_DECLARE_METATYPE( Akonadi::ImapInterval::List )
Q_DECLARE_METATYPE( Akonadi::ImapSet )
#endif

View file

@ -0,0 +1,432 @@
/*
Copyright (c) 2007 Volker Krause <vkrause@kde.org>
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
*/
#include "notificationmessage_p.h"
#include "imapparser_p.h"
#include <QtCore/QDebug>
#include <QtCore/QHash>
#include <QtDBus/QDBusMetaType>
using namespace Akonadi;
class NotificationMessage::Private : public QSharedData
{
public:
Private()
: QSharedData()
, type( NotificationMessage::InvalidType )
, operation( NotificationMessage::InvalidOp )
, uid( -1 )
, parentCollection( -1 )
, parentDestCollection( -1 )
{
}
Private( const Private &other )
: QSharedData( other )
{
sessionId = other.sessionId;
type = other.type;
operation = other.operation;
uid = other.uid;
remoteId = other.remoteId;
resource = other.resource;
destResource = other.destResource;
parentCollection = other.parentCollection;
parentDestCollection = other.parentDestCollection;
mimeType = other.mimeType;
parts = other.parts;
}
bool compareWithoutOpAndParts( const Private &other ) const
{
return uid == other.uid
&& type == other.type
&& sessionId == other.sessionId
&& remoteId == other.remoteId
&& resource == other.resource
&& destResource == other.destResource
&& parentCollection == other.parentCollection
&& parentDestCollection == other.parentDestCollection
&& mimeType == other.mimeType;
}
bool operator==( const Private &other ) const
{
return operation == other.operation && parts == other.parts && compareWithoutOpAndParts( other );
}
QByteArray sessionId;
NotificationMessage::Type type;
NotificationMessage::Operation operation;
Id uid;
QString remoteId;
QByteArray resource;
QByteArray destResource;
Id parentCollection;
Id parentDestCollection;
QString mimeType;
QSet<QByteArray> parts;
};
NotificationMessage::NotificationMessage()
: d( new Private )
{
}
NotificationMessage::NotificationMessage( const NotificationMessage &other )
: d( other.d )
{
}
NotificationMessage::~NotificationMessage()
{
}
NotificationMessage &NotificationMessage::operator=( const NotificationMessage &other )
{
if ( this != &other ) {
d = other.d;
}
return *this;
}
bool NotificationMessage::operator==( const NotificationMessage &other ) const
{
return d == other.d;
}
void NotificationMessage::registerDBusTypes()
{
qDBusRegisterMetaType<Akonadi::NotificationMessage>();
qDBusRegisterMetaType<Akonadi::NotificationMessage::List>();
}
QByteArray NotificationMessage::sessionId() const
{
return d->sessionId;
}
void NotificationMessage::setSessionId( const QByteArray &sessionId )
{
d->sessionId = sessionId;
}
NotificationMessage::Type NotificationMessage::type() const
{
return d->type;
}
void NotificationMessage::setType( Type type )
{
d->type = type;
}
NotificationMessage::Operation NotificationMessage::operation() const
{
return d->operation;
}
void NotificationMessage::setOperation( Operation operation )
{
d->operation = operation;
}
NotificationMessage::Id NotificationMessage::uid() const
{
return d->uid;
}
void NotificationMessage::setUid( Id uid )
{
d->uid = uid;
}
QString NotificationMessage::remoteId() const
{
return d->remoteId;
}
void NotificationMessage::setRemoteId( const QString &remoteId )
{
d->remoteId = remoteId;
}
QByteArray NotificationMessage::resource() const
{
return d->resource;
}
void NotificationMessage::setResource( const QByteArray &resource )
{
d->resource = resource;
}
NotificationMessage::Id NotificationMessage::parentCollection() const
{
return d->parentCollection;
}
NotificationMessage::Id NotificationMessage::parentDestCollection() const
{
return d->parentDestCollection;
}
void NotificationMessage::setParentCollection( Id parent )
{
d->parentCollection = parent;
}
void NotificationMessage::setParentDestCollection( Id parent )
{
d->parentDestCollection = parent;
}
void NotificationMessage::setDestinationResource( const QByteArray &destResource )
{
d->destResource = destResource;
}
QByteArray NotificationMessage::destinationResource() const
{
return d->destResource;
}
QString NotificationMessage::mimeType() const
{
return d->mimeType;
}
void NotificationMessage::setMimeType( const QString &mimeType )
{
d->mimeType = mimeType;
}
QSet<QByteArray> NotificationMessage::itemParts() const
{
return d->parts;
}
void NotificationMessage::setItemParts( const QSet<QByteArray> &parts )
{
d->parts = parts;
}
QString NotificationMessage::toString() const
{
QString rv;
// some tests before making the string
if ( type() == InvalidType ) {
return QLatin1String( "Error: Type is not set" );
}
if ( uid() == -1 ) {
return QLatin1String( "Error: uid is not set" );
}
if ( remoteId().isEmpty() ) {
return QLatin1String( "Error: remoteId is empty" );
}
if ( operation() == InvalidOp ) {
return QLatin1String( "Error: operation is not set" );
}
switch ( type() ) {
case Item:
rv += QLatin1String( "Item " );
break;
case Collection:
rv += QLatin1String( "Collection " );
break;
case InvalidType:
// already done above
break;
}
rv += QString::fromLatin1( "(%1, %2) " ).arg( uid() ).arg( remoteId() );
if ( parentCollection() >= 0 ) {
if ( parentDestCollection() >= 0 ) {
rv += QString::fromLatin1( "from " );
} else {
rv += QString::fromLatin1( "in " );
}
rv += QString::fromLatin1( "collection %1 " ).arg( parentCollection() );
} else {
rv += QLatin1String( "unspecified parent collection " );
}
rv += QString::fromLatin1( "mimetype %1 " ).arg( mimeType().isEmpty() ? QLatin1String( "unknown" ) : mimeType() );
switch ( operation() ) {
case Add:
rv += QLatin1String( "added" );
break;
case Modify:
rv += QLatin1String( "modified parts (" );
rv += QString::fromLatin1( ImapParser::join( itemParts().toList(), ", " ) );
rv += QLatin1String( ")" );
break;
case Move:
rv += QLatin1String( "moved" );
break;
case Remove:
rv += QLatin1String( "removed" );
break;
case Link:
rv += QLatin1String( "linked" );
break;
case Unlink:
rv += QLatin1String( "unlinked" );
break;
case Subscribe:
rv += QLatin1String( "subscribed" );
break;
case Unsubscribe:
rv += QLatin1String( "unsubscribed" );
break;
case InvalidOp:
// already done above
break;
}
if ( parentDestCollection() >= 0 ) {
rv += QString::fromLatin1( " to collection %1" ).arg( parentDestCollection() );
}
return rv;
}
void NotificationMessage::appendAndCompress( NotificationMessage::List &list, const NotificationMessage &msg )
{
bool appended;
appendAndCompress( list, msg, &appended );
}
void NotificationMessage::appendAndCompress( NotificationMessage::List &list, const NotificationMessage &msg, bool *appended )
{
// fast-path for stuff that is not considered during O(n) compression below
if ( msg.operation() != Add && msg.operation() != Link && msg.operation() != Unlink && msg.operation() != Subscribe && msg.operation() != Unsubscribe && msg.operation() != Move ) {
NotificationMessage::List::Iterator end = list.end();
for ( NotificationMessage::List::Iterator it = list.begin(); it != end; ) {
if ( msg.d.constData()->compareWithoutOpAndParts( *( ( *it ).d.constData() ) ) ) {
// same operation: merge changed parts and drop the new one
if ( msg.operation() == ( *it ).operation() ) {
( *it ).setItemParts( ( *it ).itemParts() + msg.itemParts() );
*appended = false;
return;
}
// new one is a modification, the existing one not, so drop the new one
else if ( msg.operation() == Modify ) {
*appended = false;
return;
}
// new on is a deletion, erase the existing modification ones (and keep going, in case there are more)
else if ( msg.operation() == Remove && ( *it ).operation() == Modify ) {
it = list.erase( it );
end = list.end();
}
// keep looking
else {
++it;
}
} else {
++it;
}
}
}
*appended = true;
list.append( msg );
}
QDBusArgument &operator<<( QDBusArgument &arg, const NotificationMessage &msg )
{
arg.beginStructure();
arg << msg.sessionId();
arg << msg.type();
arg << msg.operation();
arg << msg.uid();
arg << msg.remoteId();
arg << msg.resource();
arg << msg.parentCollection();
arg << msg.parentDestCollection();
arg << msg.mimeType();
QStringList itemParts;
if ( msg.operation() == NotificationMessage::Move ) {
// encode destination resource in parts, as a backward compat hack
itemParts.push_back( QString::fromLatin1( msg.destinationResource() ) );
} else {
Q_FOREACH ( const QByteArray &itemPart, msg.itemParts() ) {
itemParts.append( QString::fromLatin1( itemPart ) );
}
}
arg << itemParts;
arg.endStructure();
return arg;
}
const QDBusArgument &operator>>( const QDBusArgument &arg, NotificationMessage &msg )
{
arg.beginStructure();
QByteArray b;
arg >> b;
msg.setSessionId( b );
int i;
arg >> i;
msg.setType( static_cast<NotificationMessage::Type>( i ) );
arg >> i;
msg.setOperation( static_cast<NotificationMessage::Operation>( i ) );
NotificationMessage::Id id;
arg >> id;
msg.setUid( id );
QString s;
arg >> s;
msg.setRemoteId( s );
arg >> b;
msg.setResource( b );
arg >> id;
msg.setParentCollection( id );
arg >> id;
msg.setParentDestCollection( id );
arg >> s;
msg.setMimeType( s );
QStringList l;
arg >> l;
QSet<QByteArray> itemParts;
if ( msg.operation() == NotificationMessage::Move && l.size() >= 1 ) {
// decode destination resource, which is stored in parts as a backward compat hack
msg.setDestinationResource( l.first().toLatin1() );
} else {
Q_FOREACH ( const QString &itemPart, l ) {
itemParts.insert( itemPart.toLatin1() );
}
}
msg.setItemParts( itemParts );
arg.endStructure();
return arg;
}
uint qHash( const Akonadi::NotificationMessage &msg )
{
return qHash( msg.uid() + ( msg.type() << 31 ) + ( msg.operation() << 28 ) );
}

View file

@ -0,0 +1,136 @@
/*
Copyright (c) 2007 Volker Krause <vkrause@kde.org>
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
*/
#ifndef AKONADI_NOTIFICATIONMESSAGE_P_H
#define AKONADI_NOTIFICATIONMESSAGE_P_H
#include "akonadiprotocolinternals_export.h"
#include <QtCore/QList>
#include <QtCore/QMetaType>
#include <QtCore/QSharedDataPointer>
#include <QtDBus/QDBusArgument>
namespace Akonadi {
/**
@internal
Used for sending notification signals over DBus.
DBus type: (ayiiisayisas)
*/
class AKONADIPROTOCOLINTERNALS_EXPORT NotificationMessage
{
public:
typedef QList<NotificationMessage> List;
typedef qint64 Id;
enum Type {
InvalidType,
Collection,
Item
};
enum Operation {
InvalidOp,
Add,
Modify,
Move,
Remove,
Link,
Unlink,
Subscribe,
Unsubscribe
};
NotificationMessage();
NotificationMessage( const NotificationMessage &other );
~NotificationMessage();
NotificationMessage &operator=( const NotificationMessage &other );
bool operator==( const NotificationMessage &other ) const;
static void registerDBusTypes();
QByteArray sessionId() const;
void setSessionId( const QByteArray &sessionId );
Type type() const;
void setType( Type type );
Operation operation() const;
void setOperation( Operation operation );
Id uid() const;
void setUid( Id uid );
QString remoteId() const;
void setRemoteId( const QString &remoteId );
QByteArray resource() const;
void setResource( const QByteArray &resource );
Id parentCollection() const;
void setParentCollection( Id parent );
Id parentDestCollection() const;
void setParentDestCollection( Id parent );
QByteArray destinationResource() const;
void setDestinationResource( const QByteArray &destResource );
QString mimeType() const;
void setMimeType( const QString &mimeType );
QSet<QByteArray> itemParts() const;
void setItemParts( const QSet<QByteArray> &parts );
QString toString() const;
/**
Adds a new notification message to the given list and compresses notifications
where possible.
*/
static void appendAndCompress( NotificationMessage::List &list, const NotificationMessage &msg );
// BIC: make the above return bool.
static void appendAndCompress( NotificationMessage::List &list, const NotificationMessage &msg, bool *appended );
private:
class Private;
QSharedDataPointer<Private> d;
};
}
QDBusArgument &operator<<( QDBusArgument &arg, const Akonadi::NotificationMessage &msg );
const QDBusArgument &operator>>( const QDBusArgument &arg, Akonadi::NotificationMessage &msg );
uint qHash( const Akonadi::NotificationMessage &msg );
Q_DECLARE_TYPEINFO( Akonadi::NotificationMessage, Q_MOVABLE_TYPE );
Q_DECLARE_METATYPE( Akonadi::NotificationMessage )
Q_DECLARE_METATYPE( Akonadi::NotificationMessage::List )
// V2 is used in NotificationSource.xml interface, so it must be
// defined so that old clients that only include this header
// will compile
#include "notificationmessagev2_p.h"
#endif

View file

@ -0,0 +1,585 @@
/*
Copyright (c) 2007 Volker Krause <vkrause@kde.org>
Copyright (c) 2013 Daniel Vrátil <dvratil@redhat.com>
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
*/
#include "notificationmessagev2_p.h"
#include "notificationmessagev2_p_p.h"
#include "notificationmessage_p.h"
#include "imapparser_p.h"
#include <QtCore/QDebug>
#include <QtCore/QHash>
#include <QtDBus/QDBusMetaType>
#include <qdbusconnection.h>
using namespace Akonadi;
class NotificationMessageV2::Private : public QSharedData
{
public:
Private()
: QSharedData()
, type( InvalidType )
, operation( InvalidOp )
, parentCollection( -1 )
, parentDestCollection( -1 )
{
}
Private( const Private &other )
: QSharedData( other )
{
sessionId = other.sessionId;
type = other.type;
operation = other.operation;
items = other.items;
resource = other.resource;
destResource = other.destResource;
parentCollection = other.parentCollection;
parentDestCollection = other.parentDestCollection;
parts = other.parts;
addedFlags = other.addedFlags;
removedFlags = other.removedFlags;
addedTags = other.addedTags;
removedTags = other.removedTags;
}
QByteArray sessionId;
NotificationMessageV2::Type type;
NotificationMessageV2::Operation operation;
QMap<Id, NotificationMessageV2::Entity> items;
QByteArray resource;
QByteArray destResource;
Id parentCollection;
Id parentDestCollection;
QSet<QByteArray> parts;
QSet<QByteArray> addedFlags;
QSet<QByteArray> removedFlags;
QSet<qint64> addedTags;
QSet<qint64> removedTags;
};
NotificationMessageV2::NotificationMessageV2():
d( new Private )
{
}
NotificationMessageV2::NotificationMessageV2( const NotificationMessageV2 &other ):
d( other.d )
{
}
NotificationMessageV2::~NotificationMessageV2()
{
}
NotificationMessageV2 &NotificationMessageV2::operator=( const NotificationMessageV2 &other )
{
if ( this != &other ) {
d = other.d;
}
return *this;
}
bool NotificationMessageV2::operator==( const NotificationMessageV2 &other ) const
{
return d->operation == other.d->operation
&& d->parts == other.d->parts
&& d->addedFlags == other.d->addedFlags
&& d->removedFlags == other.d->removedFlags
&& d->addedTags == other.d->addedTags
&& d->removedTags == other.d->removedTags
&& NotificationMessageHelpers::compareWithoutOpAndParts( *this, other );
}
void NotificationMessageV2::registerDBusTypes()
{
qDBusRegisterMetaType<Akonadi::NotificationMessageV2>();
qDBusRegisterMetaType<Akonadi::NotificationMessageV2::Entity>();
qDBusRegisterMetaType<Akonadi::NotificationMessageV2::List>();
qDBusRegisterMetaType<Akonadi::NotificationMessageV2::Type>();
qDBusRegisterMetaType<QVector<QByteArray> >();
qDBusRegisterMetaType<QVector<qint64> >();
}
bool NotificationMessageV2::isValid() const
{
return d->operation != Akonadi::NotificationMessageV2::InvalidOp
&& d->type != Akonadi::NotificationMessageV2::InvalidType
&& !d->items.isEmpty();
}
void NotificationMessageV2::addEntity( Id id, const QString &remoteId, const QString &remoteRevision, const QString &mimeType )
{
NotificationMessageV2::Entity item;
item.id = id;
item.remoteId = remoteId;
item.remoteRevision = remoteRevision;
item.mimeType = mimeType;
d->items.insert( id, item );
}
void NotificationMessageV2::setEntities( const QList<NotificationMessageV2::Entity> &items )
{
clearEntities();
Q_FOREACH ( const NotificationMessageV2::Entity &item, items ) {
d->items.insert( item.id, item );
}
}
void NotificationMessageV2::clearEntities()
{
d->items.clear();
}
QMap<NotificationMessageV2::Id, NotificationMessageV2::Entity> NotificationMessageV2::entities() const
{
return d->items;
}
NotificationMessageV2::Entity NotificationMessageV2::entity( NotificationMessageV2::Id id ) const
{
return d->items.value( id );
}
QList<NotificationMessageV2::Id> NotificationMessageV2::uids() const
{
return d->items.keys();
}
QByteArray NotificationMessageV2::sessionId() const
{
return d->sessionId;
}
void NotificationMessageV2::setSessionId( const QByteArray &sessionId )
{
d->sessionId = sessionId;
}
NotificationMessageV2::Type NotificationMessageV2::type() const
{
return d->type;
}
void NotificationMessageV2::setType( Type type )
{
d->type = type;
}
NotificationMessageV2::Operation NotificationMessageV2::operation() const
{
return d->operation;
}
void NotificationMessageV2::setOperation( Operation operation )
{
d->operation = operation;
}
QByteArray NotificationMessageV2::resource() const
{
return d->resource;
}
void NotificationMessageV2::setResource( const QByteArray &resource )
{
d->resource = resource;
}
NotificationMessageV2::Id NotificationMessageV2::parentCollection() const
{
return d->parentCollection;
}
NotificationMessageV2::Id NotificationMessageV2::parentDestCollection() const
{
return d->parentDestCollection;
}
void NotificationMessageV2::setParentCollection( Id parent )
{
d->parentCollection = parent;
}
void NotificationMessageV2::setParentDestCollection( Id parent )
{
d->parentDestCollection = parent;
}
void NotificationMessageV2::setDestinationResource( const QByteArray &destResource )
{
d->destResource = destResource;
}
QByteArray NotificationMessageV2::destinationResource() const
{
return d->destResource;
}
QSet<QByteArray> NotificationMessageV2::itemParts() const
{
return d->parts;
}
void NotificationMessageV2::setItemParts( const QSet<QByteArray> &parts )
{
d->parts = parts;
}
QSet<QByteArray> NotificationMessageV2::addedFlags() const
{
return d->addedFlags;
}
void NotificationMessageV2::setAddedFlags( const QSet<QByteArray> &addedFlags )
{
d->addedFlags = addedFlags;
}
QSet<QByteArray> NotificationMessageV2::removedFlags() const
{
return d->removedFlags;
}
void NotificationMessageV2::setRemovedFlags( const QSet<QByteArray> &removedFlags )
{
d->removedFlags = removedFlags;
}
QSet<qint64> NotificationMessageV2::addedTags() const
{
return d->addedTags;
}
void NotificationMessageV2::setAddedTags( const QSet<qint64> &addedTags )
{
d->addedTags = addedTags;
}
QSet<qint64> NotificationMessageV2::removedTags() const
{
return d->removedTags;
}
void NotificationMessageV2::setRemovedTags( const QSet<qint64> &removedTags )
{
d->removedTags = removedTags;
}
QString NotificationMessageV2::toString() const
{
QString rv;
switch ( d->type ) {
case Items:
rv += QLatin1String( "Items " );
break;
case Collections:
rv += QLatin1String( "Collections " );
break;
case Tags:
rv += QLatin1String( "Tags " );
break;
case InvalidType:
return QLatin1String( "*INVALID TYPE* " );
}
QSet<QByteArray> items;
Q_FOREACH ( const NotificationMessageV2::Entity &item, d->items ) {
QString itemStr = QString::fromLatin1( "(%1,%2" ).arg( item.id ).arg( item.remoteId );
if ( !item.remoteRevision.isEmpty() ) {
itemStr += QString::fromLatin1( ",%1" ).arg( item.remoteRevision );
}
if ( !item.mimeType.isEmpty() ) {
itemStr += QString::fromLatin1( ",%1" ).arg( item.mimeType );
}
itemStr += QLatin1String( ")" );
items << itemStr.toLatin1();
}
rv += QLatin1String( "(" ) + QString::fromLatin1( ImapParser::join( items, ", " ) ) + QLatin1String( ")" );
if ( d->parentDestCollection >= 0 ) {
rv += QLatin1String( " from " );
} else {
rv += QLatin1String( " in " );
}
if ( d->parentCollection >= 0 ) {
rv += QString::fromLatin1( "collection %1 " ).arg( d->parentCollection );
} else {
rv += QLatin1String( "unspecified parent collection " );
}
switch ( d->operation ) {
case Add:
rv += QLatin1String( "added" );
break;
case Modify:
rv += QLatin1String( "modified parts (" );
rv += QString::fromLatin1( ImapParser::join( d->parts.toList(), ", " ) );
rv += QLatin1String( ")" );
break;
case ModifyFlags:
rv += QLatin1String( "added flags (" );
rv += QString::fromLatin1( ImapParser::join( d->addedFlags.toList(), ", " ) );
rv += QLatin1String( ") " );
rv += QLatin1String( "removed flags (" );
rv += QString::fromLatin1( ImapParser::join( d->removedFlags.toList(), ", " ) );
rv += QLatin1String( ") " );
break;
case ModifyTags: {
rv += QLatin1String( "added tags (" );
QList<QByteArray> tags;
Q_FOREACH ( qint64 tagId, d->addedTags ) {
tags << QByteArray::number( tagId );
}
rv += QString::fromLatin1( ImapParser::join( tags, ", " ) );
rv += QLatin1String( ") " );
tags.clear();
Q_FOREACH ( qint64 tagId, d->removedTags ) {
tags << QByteArray::number( tagId );
}
rv += QLatin1String( "removed tags (" );
rv += QString::fromLatin1( ImapParser::join( tags, ", " ) );
rv += QLatin1String( ") " );
break;
}
case Move:
rv += QLatin1String( "moved" );
break;
case Remove:
rv += QLatin1String( "removed" );
break;
case Link:
rv += QLatin1String( "linked" );
break;
case Unlink:
rv += QLatin1String( "unlinked" );
break;
case Subscribe:
rv += QLatin1String( "subscribed" );
break;
case Unsubscribe:
rv += QLatin1String( "unsubscribed" );
break;
case InvalidOp:
return QLatin1String( "*INVALID OPERATION*" );
}
if ( d->parentDestCollection >= 0 ) {
rv += QString::fromLatin1( " to collection %1" ).arg( d->parentDestCollection );
}
return rv;
}
QDBusArgument &operator<<( QDBusArgument &arg, const Akonadi::NotificationMessageV2 &msg )
{
arg.beginStructure();
arg << msg.sessionId();
arg << static_cast<int>( msg.type() );
arg << static_cast<int>( msg.operation() );
arg << msg.entities().values();
arg << msg.resource();
arg << msg.destinationResource();
arg << msg.parentCollection();
arg << msg.parentDestCollection();
QStringList itemParts;
Q_FOREACH ( const QByteArray &itemPart, msg.itemParts() ) {
itemParts.append( QString::fromLatin1( itemPart ) );
}
arg << itemParts;
arg << msg.addedFlags().toList();
arg << msg.removedFlags().toList();
arg.endStructure();
return arg;
}
const QDBusArgument &operator>>( const QDBusArgument &arg, Akonadi::NotificationMessageV2 &msg )
{
QByteArray ba;
int i;
QList<NotificationMessageV2::Entity> items;
NotificationMessageV2::Id id;
QString str;
QStringList strl;
QList<QByteArray> bal;
arg.beginStructure();
arg >> ba;
msg.setSessionId( ba );
arg >> i;
msg.setType( static_cast<NotificationMessageV2::Type>( i ) );
arg >> i;
msg.setOperation( static_cast<NotificationMessageV2::Operation>( i ) );
arg >> items;
msg.setEntities( items );
arg >> ba;
msg.setResource( ba );
arg >> ba;
msg.setDestinationResource( ba );
arg >> id;
msg.setParentCollection( id );
arg >> id;
msg.setParentDestCollection( id );
arg >> strl;
QSet<QByteArray> itemParts;
Q_FOREACH ( const QString &itemPart, strl ) {
itemParts.insert( itemPart.toLatin1() );
}
msg.setItemParts( itemParts );
arg >> bal;
msg.setAddedFlags( bal.toSet() );
arg >> bal;
msg.setRemovedFlags( bal.toSet() );
arg.endStructure();
return arg;
}
QDBusArgument &operator<<( QDBusArgument &arg, const Akonadi::NotificationMessageV2::Entity &item )
{
arg.beginStructure();
arg << item.id;
arg << item.remoteId;
arg << item.remoteRevision;
arg << item.mimeType;
arg.endStructure();
return arg;
}
const QDBusArgument &operator>>( const QDBusArgument &arg, Akonadi::NotificationMessageV2::Entity &item )
{
arg.beginStructure();
arg >> item.id;
arg >> item.remoteId;
arg >> item.remoteRevision;
arg >> item.mimeType;
arg.endStructure();
return arg;
}
QDBusArgument &operator<<( QDBusArgument &arg, Akonadi::NotificationMessageV2::Type type )
{
arg.beginStructure();
arg << static_cast<int>( type );
arg.endStructure();
return arg;
}
const QDBusArgument &operator>>( const QDBusArgument &arg, Akonadi::NotificationMessageV2::Type &type )
{
int t;
arg.beginStructure();
arg >> t;
arg.endStructure();
type = static_cast<NotificationMessageV2::Type>( t );
return arg;
}
uint qHash( const Akonadi::NotificationMessageV2 &msg )
{
uint i = 0;
Q_FOREACH ( const NotificationMessageV2::Entity &item, msg.entities() ) {
i += item.id;
}
return qHash( i + ( msg.type() << 31 ) + ( msg.operation() << 28 ) );
}
QVector<NotificationMessage> NotificationMessageV2::toNotificationV1() const
{
QVector<NotificationMessage> v1;
Q_FOREACH ( const Entity &item, d->items ) {
NotificationMessage msgv1;
msgv1.setSessionId( d->sessionId );
msgv1.setUid( item.id );
msgv1.setRemoteId( item.remoteId );
msgv1.setMimeType( item.mimeType );
msgv1.setType( static_cast<NotificationMessage::Type>( d->type ) );
if ( d->operation == ModifyFlags ) {
msgv1.setOperation( NotificationMessage::Modify );
} else {
msgv1.setOperation( static_cast<NotificationMessage::Operation>( d->operation ) );
}
msgv1.setResource( d->resource );
msgv1.setDestinationResource( d->destResource );
msgv1.setParentCollection( d->parentCollection );
msgv1.setParentDestCollection( d->parentDestCollection );
// Backward compatibility hack
QSet<QByteArray> parts;
if ( d->operation == Remove ) {
QByteArray rr = item.remoteRevision.toLatin1();
parts << ( rr.isEmpty() ? "1" : rr );
} else if ( d->operation == ModifyFlags ) {
parts << "FLAGS";
} else {
parts = d->parts;
}
msgv1.setItemParts( parts );
v1 << msgv1;
}
return v1;
}
bool NotificationMessageV2::appendAndCompress( NotificationMessageV2::List &list, const NotificationMessageV2 &msg )
{
return NotificationMessageHelpers::appendAndCompressImpl<NotificationMessageV2::List, NotificationMessageV2>( list, msg );
}
bool NotificationMessageV2::appendAndCompress( QList<NotificationMessageV2> &list, const NotificationMessageV2 &msg )
{
return NotificationMessageHelpers::appendAndCompressImpl<QList<NotificationMessageV2>, NotificationMessageV2>( list, msg );
}
QDebug operator<<( QDebug dbg, const NotificationMessageV2::Entity &entity)
{
dbg.nospace() << "(ID: " << entity.id;
if (!entity.remoteId.isEmpty()) {
dbg.nospace() << " RID: " << entity.remoteId;
}
if (!entity.remoteRevision.isEmpty()) {
dbg.nospace() << " RREV: " << entity.remoteRevision;
}
if (!entity.mimeType.isEmpty()) {
dbg.nospace() << " MimeType: " << entity.mimeType;
}
dbg.nospace() << ")";
return dbg;
}

View file

@ -0,0 +1,190 @@
/*
Copyright (c) 2007 Volker Krause <vkrause@kde.org>
Copyright (c) 2013 Daniel Vrátil <dvratil@redhat.com>
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
*/
#ifndef AKONADI_NOTIFICATIONMESSAGEV2_H
#define AKONADI_NOTIFICATIONMESSAGEV2_H
#include "akonadiprotocolinternals_export.h"
#include <QtCore/QList>
#include <QtCore/QVector>
#include <QtCore/QSet>
#include <QtCore/QQueue>
#include <QtCore/QMetaType>
#include <QtCore/QSharedDataPointer>
#include <QtCore/QVariant>
#include <QtDBus/QDBusArgument>
#include "notificationmessage_p.h"
namespace Akonadi
{
/**
@internal
Used for sending notification signals over DBus.
DBus type: (ayiia(xsss)ayayxxasaayaay)
*/
class AKONADIPROTOCOLINTERNALS_EXPORT NotificationMessageV2
{
public:
typedef QVector<NotificationMessageV2> List;
typedef qint64 Id;
enum Type {
InvalidType,
Collections,
Items,
Tags
};
// NOTE: Keep this BC with NotificationMessage - i.e. append new stuff to the end
enum Operation {
InvalidOp,
Add,
Modify,
Move,
Remove,
Link,
Unlink,
Subscribe,
Unsubscribe,
ModifyFlags,
ModifyTags
};
class Entity
{
public:
Entity()
: id( -1 )
{
}
bool operator==( const Entity &other ) const {
return id == other.id
&& remoteId == other.remoteId
&& remoteRevision == other.remoteRevision
&& mimeType == other.mimeType;
}
Id id;
QString remoteId;
QString remoteRevision;
QString mimeType;
};
NotificationMessageV2();
NotificationMessageV2( const NotificationMessageV2 &other );
~NotificationMessageV2();
NotificationMessageV2 &operator=( const NotificationMessageV2 &other );
bool operator==( const NotificationMessageV2 &other ) const;
bool operator!=( const NotificationMessageV2 &other ) const
{
return !operator==(other);
}
static void registerDBusTypes();
bool isValid() const;
NotificationMessageV2::Type type() const;
void setType( NotificationMessageV2::Type type );
NotificationMessageV2::Operation operation() const;
void setOperation( NotificationMessageV2::Operation operation );
QByteArray sessionId() const;
void setSessionId( const QByteArray &session );
void addEntity( Id id, const QString &remoteId = QString(), const QString &remoteRevision = QString(), const QString &mimeType = QString() );
void setEntities( const QList<NotificationMessageV2::Entity> &items );
QMap<Id, NotificationMessageV2::Entity> entities() const;
NotificationMessageV2::Entity entity( Id id ) const;
QList<Id> uids() const;
void clearEntities();
QByteArray resource() const;
void setResource( const QByteArray &resource );
Id parentCollection() const;
void setParentCollection( Id parent );
Id parentDestCollection() const;
void setParentDestCollection( Id parent );
QByteArray destinationResource() const;
void setDestinationResource( const QByteArray &destResource );
QSet<QByteArray> itemParts() const;
void setItemParts( const QSet<QByteArray> &parts );
QSet<QByteArray> addedFlags() const;
void setAddedFlags( const QSet<QByteArray> &parts );
QSet<QByteArray> removedFlags() const;
void setRemovedFlags( const QSet<QByteArray> &parts );
QSet<qint64> addedTags() const;
void setAddedTags( const QSet<qint64> &tags );
QSet<qint64> removedTags() const;
void setRemovedTags( const QSet<qint64> &tags );
QString toString() const;
QVector<NotificationMessage> toNotificationV1() const;
static bool appendAndCompress( NotificationMessageV2::List &list, const NotificationMessageV2 &msg );
static bool appendAndCompress( QList<NotificationMessageV2> &list, const NotificationMessageV2 &msg );
protected:
class Private;
QSharedDataPointer<Private> d;
};
} // namespace Akonadi
AKONADIPROTOCOLINTERNALS_EXPORT QDebug operator<<( QDebug debug, const Akonadi::NotificationMessageV2::Entity &entity );
const QDBusArgument &operator>>( const QDBusArgument &arg, Akonadi::NotificationMessageV2 &msg );
QDBusArgument &operator<<( QDBusArgument &arg, const Akonadi::NotificationMessageV2 &msg );
const QDBusArgument &operator>>( const QDBusArgument &arg, Akonadi::NotificationMessageV2::Entity &item );
QDBusArgument &operator<<( QDBusArgument &arg, const Akonadi::NotificationMessageV2::Entity &item );
const QDBusArgument &operator>>( const QDBusArgument &arg, Akonadi::NotificationMessageV2::Type &type );
QDBusArgument &operator<<( QDBusArgument &qrg, Akonadi::NotificationMessageV2::Type type );
uint qHash( const Akonadi::NotificationMessageV2 &msg );
Q_DECLARE_TYPEINFO( Akonadi::NotificationMessageV2, Q_MOVABLE_TYPE );
Q_DECLARE_METATYPE( Akonadi::NotificationMessageV2 )
Q_DECLARE_METATYPE( Akonadi::NotificationMessageV2::Entity )
Q_DECLARE_METATYPE( Akonadi::NotificationMessageV2::List )
Q_DECLARE_METATYPE( Akonadi::NotificationMessageV2::Type )
Q_DECLARE_METATYPE( QVector<Akonadi::NotificationMessageV2::Type> )
Q_DECLARE_METATYPE( QVector<QByteArray> )
Q_DECLARE_METATYPE( QVector<qint64> )
// V3 is used in NotificationSource.xml interface, so it must be
// defined so that old clients that only include this header
// will compile
#include "notificationmessagev3_p.h"
#endif // NOTIFICATIONMESSAGEV2_H

View file

@ -0,0 +1,115 @@
/*
Copyright (c) 2007 Volker Krause <vkrause@kde.org>
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
*/
#ifndef AKONADI_NOTIFICATIONMESSAGEV2_P_H
#define AKONADI_NOTIFICATIONMESSAGEV2_P_H
#include "notificationmessagev2_p.h"
namespace Akonadi
{
class NotificationMessageHelpers
{
public:
template<typename T>
static bool compareWithoutOpAndParts( const T &left, const T &right )
{
return left.entities() == right.entities()
&& left.type() == right.type()
&& left.sessionId() == right.sessionId()
&& left.resource() == right.resource()
&& left.destinationResource() == right.destinationResource()
&& left.parentCollection() == right.parentCollection()
&& left.parentDestCollection() == right.parentDestCollection();
}
template<typename List, typename Msg>
static bool appendAndCompressImpl( List &list, const Msg &msg )
{
// fast-path for stuff that is not considered during O(n) compression below
if ( msg.operation() != NotificationMessageV2::Add && msg.operation() != NotificationMessageV2::Link
&& msg.operation() != NotificationMessageV2::Unlink && msg.operation() != NotificationMessageV2::Subscribe
&& msg.operation() != NotificationMessageV2::Unsubscribe && msg.operation() != NotificationMessageV2::Move ) {
typename List::Iterator end = list.end();
for ( typename List::Iterator it = list.begin(); it != end; ) {
if ( compareWithoutOpAndParts( msg, ( *it ) ) ) {
// both are modifications, merge them together and drop the new one
if ( msg.operation() == NotificationMessageV2::Modify && it->operation() == NotificationMessageV2::Modify ) {
( *it ).setItemParts( ( *it ).itemParts() + msg.itemParts() );
return false;
}
else if ( msg.operation() == NotificationMessageV2::ModifyFlags && it->operation() == NotificationMessageV2::ModifyFlags ) {
( *it ).setAddedFlags( ( *it ).addedFlags() + msg.addedFlags() );
( *it ).setRemovedFlags( ( *it ).removedFlags() + msg.removedFlags() );
// If merged notifications result in no-change notification, drop both.
if ( ( *it ).addedFlags() == ( *it ).removedFlags() ) {
it = list.erase( it );
end = list.end();
}
return false;
}
else if ( msg.operation() == NotificationMessageV2::ModifyTags && it->operation() == NotificationMessageV2::ModifyTags ) {
( *it ).setAddedTags( ( *it ).addedTags() + msg.addedTags() );
( *it ).setRemovedTags( ( *it ).removedTags() + msg.removedTags() );
// If merged notification results in no-change notification, drop both
if ( ( *it ).addedTags() == ( *it ).removedTags() ) {
it = list.erase( it );
end = list.end();
}
return false;
}
// new one is a modification, the existing one not, so drop the new one
else if ( ( ( msg.operation() == NotificationMessageV2::Modify ) || ( msg.operation() == NotificationMessageV2::ModifyFlags ) )
&& ( ( *it ).operation() != NotificationMessageV2::Modify )
&& ( *it ).operation() != NotificationMessageV2::ModifyFlags
&& ( *it ).operation() != NotificationMessageV2::ModifyTags ) {
return false;
}
// new one is a deletion, erase the existing modification ones (and keep going, in case there are more)
else if ( msg.operation() == NotificationMessageV2::Remove && ( ( *it ).operation() == NotificationMessageV2::Modify || ( *it ).operation() == NotificationMessageV2::ModifyFlags || ( *it ).operation() == NotificationMessageV2::ModifyTags ) ) {
it = list.erase( it );
end = list.end();
}
// keep looking
else {
++it;
}
} else {
++it;
}
}
}
list.append( msg );
return true;
}
};
}
#endif

View file

@ -0,0 +1,215 @@
/*
Copyright (c) 2014 Daniel Vrátil <dvratil@redhat.com>
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
*/
#include "notificationmessagev3_p.h"
#include "notificationmessagev2_p_p.h"
#include <QDebug>
#include <QDBusMetaType>
using namespace Akonadi;
NotificationMessageV3::NotificationMessageV3()
: NotificationMessageV2()
{
}
NotificationMessageV3::NotificationMessageV3( const NotificationMessageV3 &other )
: NotificationMessageV2( other )
{
}
NotificationMessageV3::~NotificationMessageV3()
{
}
void NotificationMessageV3::registerDBusTypes()
{
qDBusRegisterMetaType<Akonadi::NotificationMessageV3>();
qDBusRegisterMetaType<Akonadi::NotificationMessageV3::List>();
}
NotificationMessageV2::List NotificationMessageV3::toV2List( const NotificationMessageV3::List &list )
{
NotificationMessageV2::List out;
out.reserve( list.size() );
Q_FOREACH ( const NotificationMessageV3 &v3, list ) {
out << static_cast<NotificationMessageV2>( v3 );
}
return out;
}
bool NotificationMessageV3::appendAndCompress( NotificationMessageV3::List &list, const NotificationMessageV3 &msg )
{
return NotificationMessageHelpers::appendAndCompressImpl<NotificationMessageV3::List, NotificationMessageV3>( list, msg );
}
bool NotificationMessageV3::appendAndCompress( QList<NotificationMessageV3> &list, const NotificationMessageV3 &msg )
{
return NotificationMessageHelpers::appendAndCompressImpl<QList<NotificationMessageV3>, NotificationMessageV3>( list, msg );
}
const QDBusArgument &operator>>( const QDBusArgument &arg, NotificationMessageV3 &msg )
{
QByteArray ba;
int i;
QList<NotificationMessageV2::Entity> items;
NotificationMessageV2::Id id;
QString str;
QStringList strl;
QList<QByteArray> bal;
QList<qint64> intl;
arg.beginStructure();
arg >> ba;
msg.setSessionId( ba );
arg >> i;
msg.setType( static_cast<NotificationMessageV2::Type>( i ) );
arg >> i;
msg.setOperation( static_cast<NotificationMessageV2::Operation>( i ) );
arg >> items;
msg.setEntities( items );
arg >> ba;
msg.setResource( ba );
arg >> ba;
msg.setDestinationResource( ba );
arg >> id;
msg.setParentCollection( id );
arg >> id;
msg.setParentDestCollection( id );
arg >> strl;
QSet<QByteArray> itemParts;
Q_FOREACH ( const QString &itemPart, strl ) {
itemParts.insert( itemPart.toLatin1() );
}
msg.setItemParts( itemParts );
arg >> bal;
msg.setAddedFlags( bal.toSet() );
arg >> bal;
msg.setRemovedFlags( bal.toSet() );
arg >> intl;
msg.setAddedTags( intl.toSet() );
arg >> intl;
msg.setRemovedTags( intl.toSet() );
arg.endStructure();
return arg;
}
QDBusArgument &operator<<( QDBusArgument &arg, const NotificationMessageV3 &msg )
{
arg.beginStructure();
arg << msg.sessionId();
arg << static_cast<int>( msg.type() );
arg << static_cast<int>( msg.operation() );
arg << msg.entities().values();
arg << msg.resource();
arg << msg.destinationResource();
arg << msg.parentCollection();
arg << msg.parentDestCollection();
QStringList itemParts;
Q_FOREACH ( const QByteArray &itemPart, msg.itemParts() ) {
itemParts.append( QString::fromLatin1( itemPart ) );
}
arg << itemParts;
arg << msg.addedFlags().toList();
arg << msg.removedFlags().toList();
arg << msg.addedTags().toList();
arg << msg.removedTags().toList();
arg.endStructure();
return arg;
}
QDebug operator<<( QDebug dbg, const NotificationMessageV3 &msg )
{
dbg.nospace() << "NotificationMessageV3 {\n";
dbg.nospace() << "\tType: ";
switch (msg.type()) {
case NotificationMessageV2::InvalidType:
dbg.nospace() << QLatin1String("Invalid");
break;
case NotificationMessageV2::Items:
dbg.nospace() << QLatin1String("Items");
break;
case NotificationMessageV2::Collections:
dbg.nospace() << QLatin1String("Collections");
break;
case NotificationMessageV2::Tags:
dbg.nospace() << QLatin1String("Tags");
break;
}
dbg.nospace() << '\n';
dbg.nospace() << "\tOperation: ";
switch( msg.operation()) {
case NotificationMessageV2::InvalidOp:
dbg.nospace() << QLatin1String("Invalid");
break;
case NotificationMessageV2::Add:
dbg.nospace() << QLatin1String("Add");
break;
case NotificationMessageV2::Modify:
dbg.nospace() << QLatin1String("Modify");
break;
case NotificationMessageV2::Move:
dbg.nospace() << QLatin1String("Move");
break;
case NotificationMessageV2::Remove:
dbg.nospace() << QLatin1String("Remove");
break;
case NotificationMessageV2::Link:
dbg.nospace() << QLatin1String("Link");
break;
case NotificationMessageV2::Unlink:
dbg.nospace() << QLatin1String("Unlink");
break;
case NotificationMessageV2::Subscribe:
dbg.nospace() << QLatin1String("Subscribe");
break;
case NotificationMessageV2::Unsubscribe:
dbg.nospace() << QLatin1String("Unsubscribe");
break;
case NotificationMessageV2::ModifyFlags:
dbg.nospace() << QLatin1String("ModifyFlags");
break;
case NotificationMessageV2::ModifyTags:
dbg.nospace() << QLatin1String("ModifyTags");
break;
}
dbg.nospace() << "\n";
dbg.nospace() << "\tSession: " << msg.sessionId() << "\n";
dbg.nospace() << "\tEntities: " << msg.entities().values() << "\n";
dbg.nospace() << "\tResource: " << msg.resource() << "\n";
dbg.nospace() << "\tCollection: " << msg.parentCollection() << "\n";
dbg.nospace() << "\tDestination resource: " << msg.destinationResource() << "\n";
dbg.nospace() << "\tDestination collection: " << msg.parentDestCollection() << "\n";
dbg.nospace() << "\tParts: " << msg.itemParts() << "\n";
dbg.nospace() << "\tAdded flags: " << msg.addedFlags() << "\n";
dbg.nospace() << "\tRemoved flags: " << msg.removedFlags() << "\n";
dbg.nospace() << "\tAdded tags: " << msg.addedTags() << "\n";
dbg.nospace() << "\tRemoved tags: " << msg.removedTags() << "\n";
dbg.nospace() << "}" << "\n";
return dbg;
}

View file

@ -0,0 +1,60 @@
/*
Copyright (c) 2014 Daniel Vrátil <dvratil@redhat.com>
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
*/
#ifndef AKONADI_NOTIFICATIONMESSAGEV3_H
#define AKONADI_NOTIFICATIONMESSAGEV3_H
#include "akonadiprotocolinternals_export.h"
#include "notificationmessagev2_p.h"
#include <QDBusArgument>
#include <QDebug>
namespace Akonadi
{
class AKONADIPROTOCOLINTERNALS_EXPORT NotificationMessageV3 : public Akonadi::NotificationMessageV2
{
public:
typedef QVector<NotificationMessageV3> List;
static void registerDBusTypes();
NotificationMessageV3();
NotificationMessageV3( const NotificationMessageV3 &other );
~NotificationMessageV3();
static NotificationMessageV2::List toV2List( const NotificationMessageV3::List &list );
static bool appendAndCompress( NotificationMessageV3::List &list, const NotificationMessageV3 &msg );
static bool appendAndCompress( QList<NotificationMessageV3> &list, const NotificationMessageV3 &msg );
};
}
AKONADIPROTOCOLINTERNALS_EXPORT QDebug operator<<(QDebug dbg, const Akonadi::NotificationMessageV3 &msg);
const QDBusArgument &operator>>( const QDBusArgument &arg, Akonadi::NotificationMessageV3 &msg );
QDBusArgument &operator<<( QDBusArgument &arg, const Akonadi::NotificationMessageV3 &msg );
Q_DECLARE_TYPEINFO( Akonadi::NotificationMessageV3, Q_MOVABLE_TYPE );
Q_DECLARE_METATYPE( Akonadi::NotificationMessageV3 )
Q_DECLARE_METATYPE( Akonadi::NotificationMessageV3::List )
#endif // AKONADI_NOTIFICATIONMESSAGEV3_H

170
akonadi/libs/protocol_p.h Normal file
View file

@ -0,0 +1,170 @@
/*
Copyright (c) 2007 Volker Krause <vkrause@kde.org>
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
*/
#ifndef AKONADI_PROTOCOL_P_H
#define AKONADI_PROTOCOL_P_H
/**
@file protocol_p.h Shared constants used in the communication protocol between
the Akonadi server and its clients.
@todo Fill this file with command names, item/collection property names
item part names, etc. and replace the usages accordingly.
*/
// D-Bus service names
#define AKONADI_DBUS_SERVER_SERVICE "org.freedesktop.Akonadi"
#define AKONADI_DBUS_CONTROL_SERVICE "org.freedesktop.Akonadi.Control"
#define AKONADI_DBUS_CONTROL_SERVICE_LOCK "org.freedesktop.Akonadi.Control.lock"
#define AKONADI_DBUS_AGENTSERVER_SERVICE "org.freedesktop.Akonadi.AgentServer"
#define AKONADI_DBUS_STORAGEJANITOR_SERVICE "org.freedesktop.Akonadi.Janitor"
#define AKONADI_DBUS_SERVER_SERVICE_UPGRADING "org.freedesktop.Akonadi.upgrading"
#define AKONADI_DBUS_AGENTMANAGER_PATH "/AgentManager"
#define AKONADI_DBUS_AGENTSERVER_PATH "/AgentServer"
#define AKONADI_DBUS_STORAGEJANITOR_PATH "/Janitor"
// Commands
#define AKONADI_CMD_APPEND "APPEND"
#define AKONADI_CMD_BEGIN "BEGIN"
#define AKONADI_CMD_CAPABILITY "CAPABILITY"
#define AKONADI_CMD_COLLECTION "COLLECTION"
#define AKONADI_CMD_COLLECTIONCOPY "COLCOPY"
#define AKONADI_CMD_COLLECTIONMOVE "COLMOVE"
#define AKONADI_CMD_COMMIT "COMMIT"
#define AKONADI_CMD_ITEMCOPY "COPY"
#define AKONADI_CMD_COLLECTIONCREATE "CREATE"
#define AKONADI_CMD_COLLECTIONDELETE "DELETE"
#define AKONADI_CMD_EXPUNGE "EXPUNGE"
#define AKONADI_CMD_ITEMFETCH "FETCH"
#define AKONADI_CMD_GID "GID"
#define AKONADI_CMD_HRID "HRID"
#define AKONADI_CMD_ITEMLINK "LINK"
#define AKONADI_CMD_LIST "LIST"
#define AKONADI_CMD_LOGIN "LOGIN"
#define AKONADI_CMD_LOGOUT "LOGOUT"
#define AKONADI_CMD_LSUB "LSUB"
#define AKONADI_CMD_MERGE "MERGE"
#define AKONADI_CMD_COLLECTIONMODIFY "MODIFY"
#define AKONADI_CMD_ITEMMOVE "MOVE"
#define AKONADI_CMD_ITEMDELETE "REMOVE"
#define AKONADI_CMD_RESOURCESELECT "RESSELECT"
#define AKONADI_CMD_RID "RID"
#define AKONADI_CMD_ROLLBACK "ROLLBACK"
#define AKONADI_CMD_SUBSCRIBE "SUBSCRIBE"
#define AKONADI_CMD_SEARCH "SEARCH"
#define AKONADI_CMD_SEARCH_RESULT "SEARCH_RESULT"
#define AKONADI_CMD_SEARCH_STORE "SEARCH_STORE"
#define AKONADI_CMD_SELECT "SELECT"
#define AKONADI_CMD_STATUS "STATUS"
#define AKONADI_CMD_ITEMMODIFY "STORE"
#define AKONADI_CMD_TAGAPPEND "TAGAPPEND"
#define AKONADI_CMD_TAGFETCH "TAGFETCH"
#define AKONADI_CMD_TAGREMOVE "TAGREMOVE"
#define AKONADI_CMD_TAGSTORE "TAGSTORE"
#define AKONADI_CMD_UID "UID"
#define AKONADI_CMD_ITEMUNLINK "UNLINK"
#define AKONADI_CMD_UNSUBSCRIBE "UNSUBSCRIBE"
#define AKONADI_CMD_ITEMCREATE "X-AKAPPEND"
#define AKONADI_CMD_X_AKLIST "X-AKLIST"
#define AKONADI_CMD_X_AKLSUB "X-AKLSUB"
// Command parameters
#define AKONADI_PARAM_CAPABILITY_AKAPPENDSTREAMING "AKAPPENDSTREAMING"
#define AKONADI_PARAM_ALLATTRIBUTES "ALLATTR"
#define AKONADI_PARAM_ANCESTORS "ANCESTORS"
#define AKONADI_PARAM_ATR "ATR:"
#define AKONADI_PARAM_CACHEONLY "CACHEONLY"
#define AKONADI_PARAM_CACHEDPARTS "CACHEDPARTS"
#define AKONADI_PARAM_CACHETIMEOUT "CACHETIMEOUT"
#define AKONADI_PARAM_CACHEPOLICY "CACHEPOLICY"
#define AKONADI_PARAM_CHANGEDSINCE "CHANGEDSINCE"
#define AKONADI_PARAM_CHARSET "CHARSET"
#define AKONADI_PARAM_CHECKCACHEDPARTSONLY "CHECKCACHEDPARTSONLY"
#define AKONADI_PARAM_COLLECTION "COLLECTION"
#define AKONADI_PARAM_COLLECTIONID "COLLECTIONID"
#define AKONADI_PARAM_COLLECTIONS "COLLECTIONS"
#define AKONADI_PARAM_MTIME "DATETIME"
#define AKONADI_PARAM_CAPABILITY_DIRECTSTREAMING "DIRECTSTREAMING"
#define AKONADI_PARAM_UNDIRTY "DIRTY"
#define AKONADI_PARAM_DISPLAY "DISPLAY"
#define AKONADI_PARAM_EXTERNALPAYLOAD "EXTERNALPAYLOAD"
#define AKONADI_PARAM_ENABLED "ENABLED"
#define AKONADI_PARAM_FLAGS "FLAGS"
#define AKONADI_PARAM_TAGS "TAGS"
#define AKONADI_PARAM_FULLPAYLOAD "FULLPAYLOAD"
#define AKONADI_PARAM_GID "GID"
#define AKONADI_PARAM_IGNOREERRORS "IGNOREERRORS"
#define AKONADI_PARAM_INDEX "INDEX"
#define AKONADI_PARAM_INHERIT "INHERIT"
#define AKONADI_PARAM_INTERVAL "INTERVAL"
#define AKONADI_PARAM_INVALIDATECACHE "INVALIDATECACHE"
#define AKONADI_PARAM_MIMETYPE "MIMETYPE"
#define AKONADI_PARAM_MERGE "MERGE"
#define AKONADI_PARAM_LOCALPARTS "LOCALPARTS"
#define AKONADI_PARAM_NAME "NAME"
#define AKONADI_PARAM_CAPABILITY_NOTIFY "NOTIFY"
#define AKONADI_PARAM_CAPABILITY_NOPAYLOADPATH "NOPAYLOADPATH"
#define AKONADI_PARAM_PARENT "PARENT"
#define AKONADI_PARAM_PERSISTENTSEARCH "PERSISTENTSEARCH"
#define AKONADI_PARAM_PARTS "PARTS"
#define AKONADI_PARAM_PLD "PLD:"
#define AKONADI_PARAM_PLD_RFC822 "PLD:RFC822"
#define AKONADI_PARAM_PERSISTENTSEARCH_QUERYCOLLECTIONS "QUERYCOLLECTIONS"
#define AKONADI_PARAM_PERSISTENTSEARCH_QUERYLANG "QUERYLANGUAGE"
#define AKONADI_PARAM_PERSISTENTSEARCH_QUERYSTRING "QUERYSTRING"
#define AKONADI_PARAM_QUERY "QUERY"
#define AKONADI_PARAM_RECURSIVE "RECURSIVE"
#define AKONADI_PARAM_REFERENCED "REFERENCED"
#define AKONADI_PARAM_REMOTE "REMOTE"
#define AKONADI_PARAM_REMOTEID "REMOTEID"
#define AKONADI_PARAM_REMOTEREVISION "REMOTEREVISION"
#define AKONADI_PARAM_RESOURCE "RESOURCE"
#define AKONADI_PARAM_REVISION "REV"
#define AKONADI_PARAM_SILENT "SILENT"
#define AKONADI_PARAM_DOT_SILENT ".SILENT"
#define AKONADI_PARAM_CAPABILITY_SERVERSEARCH "SERVERSEARCH"
#define AKONADI_PARAM_SIZE "SIZE"
#define AKONADI_PARAM_STATISTICS "STATISTICS"
#define AKONADI_PARAM_SYNC "SYNC"
#define AKONADI_PARAM_SYNCONDEMAND "SYNCONDEMAND"
#define AKONADI_PARAM_TAG "TAG"
#define AKONADI_PARAM_TAGID "TAGID"
#define AKONADI_PARAM_UID "UID"
#define AKONADI_PARAM_VIRTREF "VIRTREF"
#define AKONADI_PARAM_VIRTUAL "VIRTUAL"
// Flags
#define AKONADI_FLAG_GID "\\Gid"
#define AKONADI_FLAG_IGNORED "$IGNORED"
#define AKONADI_FLAG_MIMETYPE "\\MimeType"
#define AKONADI_FLAG_REMOTEID "\\RemoteId"
#define AKONADI_FLAG_REMOTEREVISION "\\RemoteRevision"
#define AKONADI_FLAG_TAG "\\Tag"
#define AKONADI_FLAG_RTAG "\\RTag"
#define AKONADI_FLAG_SEEN "\\SEEN"
// Attributes
#define AKONADI_ATTRIBUTE_HIDDEN "ATR:HIDDEN"
#define AKONADI_ATTRIBUTE_MESSAGES "MESSAGES"
#define AKONADI_ATTRIBUTE_UNSEEN "UNSEEN"
// special resource names
#define AKONADI_SEARCH_RESOURCE "akonadi_search_resource"
#endif

View file

@ -0,0 +1,14 @@
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR})
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..)
macro(add_unit_test _source)
set(_test ${_source})
get_filename_component(_name ${_source} NAME_WE)
add_executable(${_name} ${_source})
add_test(akonadi-${_name} ${_name})
target_link_libraries(${_name} akonadiprotocolinternals ${QT_QTGUI_LIBRARY} ${QT_QTTEST_LIBRARIES})
endmacro()
add_unit_test(notificationmessagetest.cpp)
add_unit_test(notificationmessagev2test.cpp)
add_unit_test(imapparserbenchmark.cpp)

View file

@ -0,0 +1,101 @@
/*
Copyright (c) 2010 Volker Krause <vkrause@kde.org>
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
*/
#include <QtTest/QTest>
#include "../imapparser_p.h"
using namespace Akonadi;
Q_DECLARE_METATYPE( QList<QByteArray> )
class ImapParserBenchmark : public QObject
{
Q_OBJECT
private Q_SLOTS:
void quote_data()
{
QTest::addColumn<QByteArray>( "input" );
QTest::newRow( "empty" ) << QByteArray();
QTest::newRow( "10-idle" ) << QByteArray( "ababababab" );
QTest::newRow( "10-quote" ) << QByteArray( "\"abababab\"" );
QTest::newRow( "50-idle" ) << QByteArray( "ababababababababababababababababababababababababab" );
QTest::newRow( "50-quote" ) << QByteArray( "\"abababab\ncabababab\ncabababab\ncabababab\ncabababab\"" );
}
void quote()
{
QFETCH( QByteArray, input );
QBENCHMARK {
ImapParser::quote( input );
}
}
void join_data()
{
QTest::addColumn<QList<QByteArray> >( "list" );
QTest::newRow( "empty" ) << QList<QByteArray>();
QTest::newRow( "single" ) << ( QList<QByteArray>() << "ababab" );
QTest::newRow( "two" ) << ( QList<QByteArray>() << "ababab" << "ababab" );
QTest::newRow( "five" ) << ( QList<QByteArray>() << "ababab" << "ababab" << "ababab" << "ababab" << "ababab" );
QList<QByteArray> list;
for ( int i = 0; i < 50; ++i ) {
list << "ababab";
}
QTest::newRow( "a lot" ) << list;
}
void join()
{
QFETCH( QList<QByteArray>, list );
QBENCHMARK {
ImapParser::join( list, " " );
}
}
void parseParenthesizedList_data()
{
QTest::addColumn<QByteArray>( "data" );
QTest::newRow( "empty" ) << QByteArray();
QTest::newRow( "unnested" ) << QByteArray("(\"Foo Bar\" NIL \"foobar\" \"test.com\")");
QTest::newRow( "nested" ) << QByteArray("((\"Foo Bar\" NIL \"foobar\" \"test.com\"))");
QTest::newRow( "nested-long" ) << QByteArray("(UID 86 REV 0 MIMETYPE \"message/rfc822\" COLLECTIONID 13 SIZE 6114 FLAGS (\\SEEN)"
" ANCESTORS ((13 \"/INBOX\") (12 \"imap://mail@mail.test.com/\") (0 \"\")) PLD:ENVELOPE[1] {396}"
" (\"Fri, 04 Jun 2010 09:07:54 +0200\" \"Re: [ADMIN] foobar available again!\""
" ((\"Foo Bar\" NIL \"foobar\" \"test.com\"))"
" NIL NIL"
" ((\"Asdf Bla Blub\" NIL \"asdf.bla.blub\" \"123test.org\"))"
" ((NIL NIL \"muh.kuh\" \"lalala.com\") (\"Konqi KDE\" NIL \"konqi\" \"kde.org\") (NIL NIL \"all\" \"test.com\"))"
" NIL \"<201006040905.33367.foo.bar@test.com>\" \"<4C08A64A.9020205@123test.org>\""
" \"<201006040142.56540.muh.kuh@lalala.com> <201006040704.39648.konqi@kde.org> <201006040905.33367.foo.bar@test.com>\""
"))");
}
void parseParenthesizedList()
{
QFETCH( QByteArray, data );
QVarLengthArray<QByteArray, 16> result;
QBENCHMARK {
ImapParser::parseParenthesizedList( data, result, 0 );
}
}
};
#include "imapparserbenchmark.moc"
QTEST_APPLESS_MAIN( ImapParserBenchmark )

View file

@ -0,0 +1,155 @@
/*
Copyright (c) 2007 Volker Krause <vkrause@kde.org>
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
*/
#include "notificationmessagetest.h"
#include <notificationmessage_p.h>
#include <QSet>
#include <QtTest/QTest>
QTEST_APPLESS_MAIN( NotificationMessageTest )
using namespace Akonadi;
Q_DECLARE_METATYPE( NotificationMessage::Type )
void NotificationMessageTest::testCompress()
{
NotificationMessage::List list;
NotificationMessage msg;
msg.setType( NotificationMessage::Item );
msg.setOperation( NotificationMessage::Add );
NotificationMessage::appendAndCompress( list, msg );
QCOMPARE( list.count(), 1 );
msg.setOperation( NotificationMessage::Modify );
NotificationMessage::appendAndCompress( list, msg );
QCOMPARE( list.count(), 1 );
QCOMPARE( list.first().operation(), NotificationMessage::Add );
msg.setOperation( NotificationMessage::Remove );
NotificationMessage::appendAndCompress( list, msg );
QCOMPARE( list.count(), 2 ); // should be 2 for collections, 0 for items?
}
void NotificationMessageTest::testCompress2()
{
NotificationMessage::List list;
NotificationMessage msg;
msg.setType( NotificationMessage::Item );
msg.setOperation( NotificationMessage::Modify );
NotificationMessage::appendAndCompress( list, msg );
QCOMPARE( list.count(), 1 );
msg.setOperation( NotificationMessage::Remove );
NotificationMessage::appendAndCompress( list, msg );
QCOMPARE( list.count(), 1 );
QCOMPARE( list.first().operation(), NotificationMessage::Remove );
}
void NotificationMessageTest::testCompress3()
{
NotificationMessage::List list;
NotificationMessage msg;
msg.setType( NotificationMessage::Item );
msg.setOperation( NotificationMessage::Modify );
NotificationMessage::appendAndCompress( list, msg );
QCOMPARE( list.count(), 1 );
NotificationMessage::appendAndCompress( list, msg );
QCOMPARE( list.count(), 1 );
}
void NotificationMessageTest::testCompressWithItemParts()
{
NotificationMessage::List list;
NotificationMessage msg;
msg.setType( NotificationMessage::Item );
msg.setOperation( NotificationMessage::Add );
NotificationMessage::appendAndCompress( list, msg );
QCOMPARE( list.count(), 1 );
msg.setOperation( NotificationMessage::Modify );
QSet<QByteArray> changes;
changes.insert( "FLAGS" );
msg.setItemParts( changes );
NotificationMessage::appendAndCompress( list, msg );
NotificationMessage::appendAndCompress( list, msg );
QCOMPARE( list.count(), 1 );
QCOMPARE( list.first().operation(), NotificationMessage::Add );
QCOMPARE( list.first().itemParts(), QSet<QByteArray>() );
list.clear();
NotificationMessage::appendAndCompress( list, msg );
QCOMPARE( list.count(), 1 );
msg.setOperation( NotificationMessage::Remove );
msg.setItemParts( QSet<QByteArray>() );
NotificationMessage::appendAndCompress( list, msg );
QCOMPARE( list.count(), 1 );
QCOMPARE( list.first().operation(), NotificationMessage::Remove );
QCOMPARE( list.first().itemParts(), QSet<QByteArray>() );
}
void NotificationMessageTest::testNoCompress()
{
NotificationMessage::List list;
NotificationMessage msg;
msg.setType( NotificationMessage::Item );
msg.setOperation( NotificationMessage::Modify );
NotificationMessage::appendAndCompress( list, msg );
QCOMPARE( list.count(), 1 );
msg.setType( NotificationMessage::Collection );
NotificationMessage::appendAndCompress( list, msg );
QCOMPARE( list.count(), 2 );
}
void NotificationMessageTest::testPartModificationMerge_data()
{
QTest::addColumn<NotificationMessage::Type>( "type" );
QTest::newRow( "item" ) << NotificationMessage::Item;
QTest::newRow( "collection" ) << NotificationMessage::Collection;
}
void NotificationMessageTest::testPartModificationMerge()
{
QFETCH( NotificationMessage::Type, type );
NotificationMessage::List list;
NotificationMessage msg;
msg.setType( type );
msg.setOperation( NotificationMessage::Modify );
msg.setItemParts( QSet<QByteArray>() << "PART1" );
NotificationMessage::appendAndCompress( list, msg );
QCOMPARE( list.count(), 1 );
msg.setItemParts( QSet<QByteArray>() << "PART2" );
NotificationMessage::appendAndCompress( list, msg );
QCOMPARE( list.count(), 1 );
QCOMPARE( list.first().itemParts(), ( QSet<QByteArray>() << "PART1" << "PART2" ) );
}

View file

@ -0,0 +1,38 @@
/*
Copyright (c) 2007 Volker Krause <vkrause@kde.org>
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
*/
#ifndef AKONADI_NOTIFICATIONMESSAGETEST_H
#define AKONADI_NOTIFICATIONMESSAGETEST_H
#include <QtCore/QObject>
class NotificationMessageTest : public QObject
{
Q_OBJECT
private Q_SLOTS:
void testCompress();
void testCompress2();
void testCompress3();
void testCompressWithItemParts();
void testNoCompress();
void testPartModificationMerge_data();
void testPartModificationMerge();
};
#endif

View file

@ -0,0 +1,248 @@
/*
Copyright (c) 2007 Volker Krause <vkrause@kde.org>
Copyright (c) 2013 Daniel Vrátil <dvratil@redhat.com>
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
*/
#include "notificationmessagev2test.h"
#include <notificationmessagev2_p.h>
#include <QSet>
#include <QtTest/QTest>
QTEST_APPLESS_MAIN( NotificationMessageV2Test )
using namespace Akonadi;
void NotificationMessageV2Test::testCompress()
{
NotificationMessageV2::List list;
NotificationMessageV2 msg;
msg.setType( NotificationMessageV2::Items );
msg.setOperation( NotificationMessageV2::Add );
NotificationMessageV2::appendAndCompress( list, msg );
QCOMPARE( list.count(), 1 );
msg.setOperation( NotificationMessageV2::Modify );
NotificationMessageV2::appendAndCompress( list, msg );
QCOMPARE( list.count(), 1 );
QCOMPARE( list.first().operation(), NotificationMessageV2::Add );
msg.setOperation( NotificationMessageV2::Remove );
NotificationMessageV2::appendAndCompress( list, msg );
QCOMPARE( list.count(), 2 ); // should be 2 for collections, 0 for items?
}
void NotificationMessageV2Test::testCompress2()
{
NotificationMessageV2::List list;
NotificationMessageV2 msg;
msg.setType( NotificationMessageV2::Items );
msg.setOperation( NotificationMessageV2::Modify );
NotificationMessageV2::appendAndCompress( list, msg );
QCOMPARE( list.count(), 1 );
msg.setOperation( NotificationMessageV2::Remove );
NotificationMessageV2::appendAndCompress( list, msg );
QCOMPARE( list.count(), 1 );
QCOMPARE( list.first().operation(), NotificationMessageV2::Remove );
}
void NotificationMessageV2Test::testCompress3()
{
NotificationMessageV2::List list;
NotificationMessageV2 msg;
msg.setType( NotificationMessageV2::Items );
msg.setOperation( NotificationMessageV2::Modify );
msg.setItemParts( QSet<QByteArray>() << "PART1" );
NotificationMessageV2::appendAndCompress( list, msg );
QCOMPARE( list.count(), 1 );
NotificationMessageV2 msg2;
msg2.setType( NotificationMessageV2::Items );
msg2.setOperation( NotificationMessageV2::Modify );
msg2.setItemParts( QSet<QByteArray>() << "PART2" );
NotificationMessageV2::appendAndCompress( list, msg2 );
QCOMPARE( list.count(), 1 );
QCOMPARE( list.first().itemParts(), QSet<QByteArray>() << "PART1" << "PART2" );
}
void NotificationMessageV2Test::testCompress4()
{
NotificationMessageV2::List list;
NotificationMessageV2 msg;
msg.setType( NotificationMessageV2::Items );
msg.setOperation( NotificationMessageV2::ModifyFlags );
QSet<QByteArray> set;
set << "FLAG1";
msg.setAddedFlags( set );
NotificationMessageV2::appendAndCompress( list, msg );
QCOMPARE( list.count(), 1 );
set.clear();
msg.setAddedFlags( set );
set << "FLAG2";
msg.setRemovedFlags( set );
NotificationMessageV2::appendAndCompress( list, msg );
QCOMPARE( list.count(), 1 );
QCOMPARE( list.first().addedFlags(), ( QSet<QByteArray>() << "FLAG1" ) );
QCOMPARE( list.first().removedFlags(), ( QSet<QByteArray>() << "FLAG2" ) );
}
void NotificationMessageV2Test::testCompress5()
{
NotificationMessageV2::List list;
NotificationMessageV2 msg;
msg.setType( NotificationMessageV2::Items );
msg.setOperation( NotificationMessageV2::ModifyFlags );
msg.setAddedFlags( QSet<QByteArray>() << "FLAG1" << "FLAG2" );
NotificationMessageV2::appendAndCompress( list, msg );
QCOMPARE( list.count(), 1 );
NotificationMessageV2 msg2;
msg2.setType( NotificationMessageV2::Items );
msg2.setOperation( NotificationMessageV2::Add );
msg2.setAddedFlags( QSet<QByteArray>() );
NotificationMessageV2::appendAndCompress( list, msg2 );
msg.setAddedFlags( QSet<QByteArray>() );
msg.setRemovedFlags( QSet<QByteArray>() << "FLAG2" << "FLAG1" );
NotificationMessageV2::appendAndCompress( list, msg );
QCOMPARE( list.count(), 1 );
QCOMPARE( list.first().operation(), NotificationMessageV2::Add );
}
void NotificationMessageV2Test::testCompress6()
{
NotificationMessageV2::List list;
NotificationMessageV2 msg;
msg.setType( NotificationMessageV2::Items );
msg.setOperation( NotificationMessageV2::ModifyFlags );
msg.setAddedFlags( QSet<QByteArray>() << "FLAG1" );
NotificationMessageV2::appendAndCompress( list, msg );
QCOMPARE( list.count(), 1 );
NotificationMessageV2 msg2;
msg2.setType( NotificationMessageV2::Items );
msg2.setOperation( NotificationMessageV2::ModifyFlags );
msg2.setAddedFlags( QSet<QByteArray>() << "FLAG2" );
NotificationMessageV2::appendAndCompress( list, msg2 );
QCOMPARE( list.count(), 1 );
QCOMPARE( list.first().operation(), NotificationMessageV2::ModifyFlags );
QCOMPARE( list.first().addedFlags(), QSet<QByteArray>() << "FLAG1" << "FLAG2" );
}
void NotificationMessageV2Test::testCompress7()
{
NotificationMessageV2::List list;
NotificationMessageV2 msg;
msg.setType( NotificationMessageV2::Items );
msg.setOperation( NotificationMessageV2::Modify );
msg.setItemParts( QSet<QByteArray>() << "PART1" );
NotificationMessageV2::appendAndCompress( list, msg );
QCOMPARE( list.count(), 1 );
NotificationMessageV2 msg2;
msg2.setType( NotificationMessageV2::Items );
msg2.setOperation( NotificationMessageV2::ModifyFlags );
msg2.setAddedFlags( QSet<QByteArray>() << "FLAG1" );
NotificationMessageV2::appendAndCompress( list, msg2 );
QCOMPARE( list.count(), 2 );
}
void NotificationMessageV2Test::testCompressWithItemParts()
{
NotificationMessageV2::List list;
NotificationMessageV2 msg;
msg.setType( NotificationMessageV2::Items );
msg.setOperation( NotificationMessageV2::Add );
NotificationMessageV2::appendAndCompress( list, msg );
QCOMPARE( list.count(), 1 );
msg.setOperation( NotificationMessageV2::Modify );
QSet<QByteArray> parts;
parts << "SomePart";
msg.setAddedFlags( parts );
NotificationMessageV2::appendAndCompress( list, msg );
NotificationMessageV2::appendAndCompress( list, msg );
QCOMPARE( list.count(), 1 );
QCOMPARE( list.first().operation(), NotificationMessageV2::Add );
QCOMPARE( list.first().itemParts(), QSet<QByteArray>() );
list.clear();
NotificationMessageV2::appendAndCompress( list, msg );
QCOMPARE( list.count(), 1 );
msg.setOperation( NotificationMessageV2::Remove );
msg.setItemParts( QSet<QByteArray>() );
NotificationMessageV2::appendAndCompress( list, msg );
QCOMPARE( list.count(), 1 );
QCOMPARE( list.first().operation(), NotificationMessageV2::Remove );
QCOMPARE( list.first().itemParts(), QSet<QByteArray>() );
}
void NotificationMessageV2Test::testNoCompress()
{
NotificationMessageV2::List list;
NotificationMessageV2 msg;
msg.setType( NotificationMessageV2::Items );
msg.setOperation( NotificationMessageV2::Modify );
NotificationMessageV2::appendAndCompress( list, msg );
QCOMPARE( list.count(), 1 );
msg.setType( NotificationMessageV2::Collections );
NotificationMessageV2::appendAndCompress( list, msg );
QCOMPARE( list.count(), 2 );
}
void NotificationMessageV2Test::testPartModificationMerge_data()
{
QTest::addColumn<NotificationMessageV2::Type>( "type" );
QTest::newRow( "item" ) << NotificationMessageV2::Items;
QTest::newRow( "collection" ) << NotificationMessageV2::Collections;
}
void NotificationMessageV2Test::testPartModificationMerge()
{
QFETCH( NotificationMessageV2::Type, type );
NotificationMessageV2::List list;
NotificationMessageV2 msg;
msg.setType( type );
msg.setOperation( NotificationMessageV2::Modify );
msg.setItemParts( QSet<QByteArray>() << "PART1" );
NotificationMessageV2::appendAndCompress( list, msg );
QCOMPARE( list.count(), 1 );
msg.setItemParts( QSet<QByteArray>() << "PART2" );
NotificationMessageV2::appendAndCompress( list, msg );
QCOMPARE( list.count(), 1 );
QCOMPARE( list.first().itemParts(), ( QSet<QByteArray>() << "PART1" << "PART2" ) );
}

View file

@ -0,0 +1,43 @@
/*
Copyright (c) 2007 Volker Krause <vkrause@kde.org>
Copyright (c) 2013 Daniel Vrátil <dvratil@redhat.com>
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
*/
#ifndef AKONADI_NOTIFICATIONMESSAGEV2TEST_H
#define AKONADI_NOTIFICATIONMESSAGEV2TEST_H
#include <QtCore/QObject>
class NotificationMessageV2Test : public QObject
{
Q_OBJECT
private Q_SLOTS:
void testCompress();
void testCompress2();
void testCompress3();
void testCompress4();
void testCompress5();
void testCompress6();
void testCompress7();
void testCompressWithItemParts();
void testNoCompress();
void testPartModificationMerge_data();
void testPartModificationMerge();
};
#endif

View file

@ -0,0 +1,501 @@
/***************************************************************************
* Copyright (C) 2007 by Kevin Krammer <kevin.krammer@gmx.at> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Library General Public License as *
* published by the Free Software Foundation; either version 2 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 Library General Public *
* License along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#include "xdgbasedirs_p.h"
#include "akonadi-prefix.h" // for prefix defines
#include <QtCore/QCoreApplication>
#include <QtCore/QDebug>
#include <QtCore/QDir>
#include <QtCore/QFileInfo>
#include <QtCore/QProcess>
#include <QtCore/QSettings>
#include <cstdlib>
static QStringList alternateExecPaths( const QString &path )
{
QStringList pathList;
pathList << path;
#if defined(Q_OS_WIN) //krazy:exclude=cpp
pathList << path + QLatin1String( ".exe" );
#elif defined(Q_OS_MAC) //krazy:exclude=cpp
pathList << path + QLatin1String( ".app/Contents/MacOS/" ) + path.section( QLatin1Char( '/' ), -1 );
#endif
return pathList;
}
static QStringList splitPathList( const QString &pathList )
{
#if defined(Q_OS_WIN) //krazy:exclude=cpp
return pathList.split( QLatin1Char( ';' ) );
#else
return pathList.split( QLatin1Char( ':' ) );
#endif
}
namespace Akonadi {
class XdgBaseDirsPrivate
{
public:
XdgBaseDirsPrivate()
{
}
~XdgBaseDirsPrivate()
{
}
};
class XdgBaseDirsSingleton
{
public:
QString homePath( const char *variable, const char *defaultSubDir );
QStringList systemPathList( const char *variable, const char *defaultDirList );
public:
QString mConfigHome;
QString mDataHome;
QStringList mConfigDirs;
QStringList mDataDirs;
QStringList mExecutableDirs;
QStringList mPluginDirs;
};
Q_GLOBAL_STATIC( XdgBaseDirsSingleton, instance )
}
using namespace Akonadi;
XdgBaseDirs::XdgBaseDirs()
: d( new XdgBaseDirsPrivate() )
{
}
XdgBaseDirs::~XdgBaseDirs()
{
delete d;
}
QString XdgBaseDirs::homePath( const char *resource )
{
if ( qstrncmp( "data", resource, 4 ) == 0 ) {
if ( instance()->mDataHome.isEmpty() ) {
instance()->mDataHome = instance()->homePath( "XDG_DATA_HOME", ".local/share" );
}
return instance()->mDataHome;
} else if ( qstrncmp( "config", resource, 6 ) == 0 ) {
if ( instance()->mConfigHome.isEmpty() ) {
instance()->mConfigHome = instance()->homePath( "XDG_CONFIG_HOME", ".config" );
}
return instance()->mConfigHome;
}
return QString();
}
QStringList XdgBaseDirs::systemPathList( const char *resource )
{
if ( qstrncmp( "data", resource, 4 ) == 0 ) {
if ( instance()->mDataDirs.isEmpty() ) {
#ifdef Q_OS_WIN
QDir dir( QCoreApplication::applicationDirPath() );
dir.cdUp();
const QString defaultPathList = dir.absoluteFilePath( QLatin1String( "share" ) );
QStringList dataDirs = instance()->systemPathList( "XDG_DATA_DIRS", defaultPathList.toLocal8Bit().constData() );
#else
QStringList dataDirs = instance()->systemPathList( "XDG_DATA_DIRS", "/usr/local/share:/usr/share" );
#endif
#ifdef Q_OS_WIN
const QString prefixDataDir = QLatin1String( AKONADIPREFIX "/" AKONADIDATA );
#else
const QString prefixDataDir = QLatin1String( AKONADIDATA );
#endif
if ( !dataDirs.contains( prefixDataDir ) ) {
dataDirs << prefixDataDir;
}
#if QT_VERSION < 0x050000
// fallback for users with KDE in a different prefix and not correctly set up XDG_DATA_DIRS, hi David ;-)
QProcess proc;
// ### should probably rather be --path xdg-something
const QStringList args = QStringList() << QLatin1String( "--prefix" );
proc.start( QLatin1String( "kde4-config" ), args );
if ( proc.waitForStarted() && proc.waitForFinished() && proc.exitCode() == 0 ) {
proc.setReadChannel( QProcess::StandardOutput );
Q_FOREACH ( const QString &basePath, splitPathList( QString::fromLocal8Bit( proc.readLine().trimmed() ) ) ) {
const QString path = basePath + QDir::separator() + QLatin1String( "share" );
if ( !dataDirs.contains( path ) ) {
dataDirs << path;
}
}
}
#endif
instance()->mDataDirs = dataDirs;
}
#ifdef Q_OS_WIN
QStringList dataDirs = instance()->mDataDirs;
// on Windows installation might be scattered across several directories
// so check if any installer providing agents has registered its base path
QSettings agentProviders( QSettings::SystemScope, QLatin1String( "Akonadi" ), QLatin1String( "Akonadi" ) );
agentProviders.beginGroup( QLatin1String( "AgentProviders" ) );
Q_FOREACH ( const QString &agentProvider, agentProviders.childKeys() ) {
const QString basePath = agentProviders.value( agentProvider ).toString();
if ( !basePath.isEmpty() ) {
const QString path = basePath + QDir::separator() + QLatin1String( "share" );
if ( !dataDirs.contains( path ) ) {
dataDirs << path;
}
}
}
return dataDirs;
#else
return instance()->mDataDirs;
#endif
} else if ( qstrncmp( "config", resource, 6 ) == 0 ) {
if ( instance()->mConfigDirs.isEmpty() ) {
#ifdef Q_OS_WIN
QDir dir( QCoreApplication::applicationDirPath() );
dir.cdUp();
const QString defaultPathList = dir.absoluteFilePath( QLatin1String( "etc" ) ) + QLatin1Char( ';' ) + dir.absoluteFilePath( QLatin1String( "share/config" ) );
QStringList configDirs = instance()->systemPathList( "XDG_CONFIG_DIRS", defaultPathList.toLocal8Bit().constData() );
#else
QStringList configDirs = instance()->systemPathList( "XDG_CONFIG_DIRS", "/etc/xdg" );
#endif
#ifdef Q_OS_WIN
const QString prefixConfigDir = QLatin1String( AKONADIPREFIX "/" AKONADICONFIG );
#else
const QString prefixConfigDir = QLatin1String( AKONADICONFIG );
#endif
if ( !configDirs.contains( prefixConfigDir ) ) {
configDirs << prefixConfigDir;
}
instance()->mConfigDirs = configDirs;
}
return instance()->mConfigDirs;
}
return QStringList();
}
QString XdgBaseDirs::findResourceFile( const char *resource, const QString &relPath )
{
const QString fullPath = homePath( resource ) + QLatin1Char( '/' ) + relPath;
QFileInfo fileInfo( fullPath );
if ( fileInfo.exists() && fileInfo.isFile() && fileInfo.isReadable() ) {
return fullPath;
}
const QStringList pathList = systemPathList( resource );
Q_FOREACH ( const QString &path, pathList ) {
fileInfo = QFileInfo( path + QLatin1Char( '/' ) + relPath );
if ( fileInfo.exists() && fileInfo.isFile() && fileInfo.isReadable() ) {
return fileInfo.absoluteFilePath();
}
}
return QString();
}
QString XdgBaseDirs::findExecutableFile( const QString &relPath, const QStringList &searchPath )
{
if ( instance()->mExecutableDirs.isEmpty() ) {
QStringList executableDirs = instance()->systemPathList( "PATH", "/usr/local/bin:/usr/bin" );
const QString prefixExecutableDir = QLatin1String( AKONADIPREFIX "/bin" );
if ( !executableDirs.contains( prefixExecutableDir ) ) {
executableDirs << prefixExecutableDir;
}
if ( QCoreApplication::instance() != 0 ) {
const QString appExecutableDir = QCoreApplication::instance()->applicationDirPath();
if ( !executableDirs.contains( appExecutableDir ) ) {
executableDirs << appExecutableDir;
}
}
executableDirs += searchPath;
#if defined(Q_OS_MAC) //krazy:exclude=cpp
executableDirs += QLatin1String( AKONADIBUNDLEPATH );
#endif
qWarning() << "search paths: " << executableDirs;
instance()->mExecutableDirs = executableDirs;
}
#ifdef Q_OS_WIN
QStringList executableDirs = instance()->mExecutableDirs;
// on Windows installation might be scattered across several directories
// so check if any installer providing agents has registered its base path
QSettings agentProviders( QSettings::SystemScope, QLatin1String( "Akonadi" ), QLatin1String( "Akonadi" ) );
agentProviders.beginGroup( QLatin1String( "AgentProviders" ) );
Q_FOREACH ( const QString &agentProvider, agentProviders.childKeys() ) {
const QString basePath = agentProviders.value( agentProvider ).toString();
if ( !basePath.isEmpty() ) {
const QString path = basePath + QDir::separator() + QLatin1String( "bin" );
if ( !executableDirs.contains( path ) ) {
executableDirs << path;
}
}
}
QStringList::const_iterator pathIt = executableDirs.constBegin();
const QStringList::const_iterator pathEndIt = executableDirs.constEnd();
#else
QStringList::const_iterator pathIt = instance()->mExecutableDirs.constBegin();
const QStringList::const_iterator pathEndIt = instance()->mExecutableDirs.constEnd();
#endif
for ( ; pathIt != pathEndIt; ++pathIt ) {
const QStringList fullPathList = alternateExecPaths( *pathIt + QLatin1Char( '/' ) + relPath );
QStringList::const_iterator it = fullPathList.constBegin();
const QStringList::const_iterator endIt = fullPathList.constEnd();
for ( ; it != endIt; ++it ) {
const QFileInfo fileInfo( *it );
// resolve symlinks, happens eg. with Maemo optify
if ( fileInfo.canonicalFilePath().isEmpty() ) {
continue;
}
const QFileInfo canonicalFileInfo( fileInfo.canonicalFilePath() );
if ( canonicalFileInfo.exists() && canonicalFileInfo.isFile() && canonicalFileInfo.isExecutable() ) {
return *it;
}
}
}
return QString();
}
QStringList XdgBaseDirs::findPluginDirs()
{
if ( instance()->mPluginDirs.isEmpty() ) {
QStringList pluginDirs = instance()->systemPathList( "QT_PLUGIN_PATH", AKONADILIB ":" AKONADILIB "/qt4/plugins/:" AKONADILIB "/kde4/:" AKONADILIB "/kde4/plugins/:/usr/lib/qt4/plugins/" );
if ( QCoreApplication::instance() != 0 ) {
Q_FOREACH ( const QString &libraryPath, QCoreApplication::instance()->libraryPaths() ) {
if ( !pluginDirs.contains( libraryPath ) ) {
pluginDirs << libraryPath;
}
}
}
// fallback for users with KDE in a different prefix and not correctly set up XDG_DATA_DIRS, hi David ;-)
QProcess proc;
// ### should probably rather be --path xdg-something
const QStringList args = QStringList() << QLatin1String( "--path" ) << QLatin1String( "module" );
proc.start( QLatin1String( "kde4-config" ), args );
if ( proc.waitForStarted() && proc.waitForFinished() && proc.exitCode() == 0 ) {
proc.setReadChannel( QProcess::StandardOutput );
Q_FOREACH ( const QString &path, splitPathList( QString::fromLocal8Bit( proc.readLine().trimmed() ) ) ) {
if ( !pluginDirs.contains( path ) ) {
pluginDirs.append( path );
}
}
}
qWarning() << "search paths: " << pluginDirs;
instance()->mPluginDirs = pluginDirs;
}
return instance()->mPluginDirs;
}
QString XdgBaseDirs::findPluginFile( const QString &relPath, const QStringList &searchPath )
{
const QStringList searchDirs = findPluginDirs() + searchPath;
#if defined(Q_OS_WIN) //krazy:exclude=cpp
const QString pluginName = relPath + QLatin1String( ".dll" );
#else
const QString pluginName = relPath + QLatin1String( ".so" );
#endif
Q_FOREACH ( const QString &path, searchDirs ) {
const QFileInfo fileInfo( path + QDir::separator() + pluginName );
// resolve symlinks, happens eg. with Maemo optify
if ( fileInfo.canonicalFilePath().isEmpty() ) {
continue;
}
const QFileInfo canonicalFileInfo( fileInfo.canonicalFilePath() );
if ( canonicalFileInfo.exists() && canonicalFileInfo.isFile() ) {
return canonicalFileInfo.absoluteFilePath();
}
}
return QString();
}
QString XdgBaseDirs::findResourceDir( const char *resource, const QString &relPath )
{
QString fullPath = homePath( resource ) + QLatin1Char( '/' ) + relPath;
QFileInfo fileInfo( fullPath );
if ( fileInfo.exists() && fileInfo.isDir() && fileInfo.isReadable() ) {
return fullPath;
}
Q_FOREACH ( const QString &path, systemPathList( resource ) ) {
fileInfo = QFileInfo( path + QLatin1Char( '/' ) + relPath );
if ( fileInfo.exists() && fileInfo.isDir() && fileInfo.isReadable() ) {
return fileInfo.absoluteFilePath();
}
}
return QString();
}
QStringList XdgBaseDirs::findAllResourceDirs( const char *resource, const QString &relPath )
{
QStringList resultList;
const QString fullPath = homePath( resource ) + QLatin1Char( '/' ) + relPath;
QFileInfo fileInfo( fullPath );
if ( fileInfo.exists() && fileInfo.isDir() && fileInfo.isReadable() ) {
resultList << fileInfo.absoluteFilePath();
}
Q_FOREACH ( const QString &path, systemPathList( resource ) ) {
fileInfo = QFileInfo( path + QLatin1Char( '/' ) + relPath );
if ( fileInfo.exists() && fileInfo.isDir() && fileInfo.isReadable() ) {
const QString absPath = fileInfo.absoluteFilePath();
if ( !resultList.contains( absPath ) ) {
resultList << absPath;
}
}
}
return resultList;
}
QString XdgBaseDirs::saveDir( const char *resource, const QString &relPath )
{
const QString fullPath = homePath( resource ) + QLatin1Char( '/' ) + relPath;
QFileInfo fileInfo( fullPath );
if ( fileInfo.exists() ) {
if ( fileInfo.isDir() ) {
return fullPath;
} else {
qWarning() << "XdgBaseDirs::saveDir: '" << fileInfo.absoluteFilePath()
<< "' exists but is not a directory";
}
} else {
if ( !QDir::home().mkpath( fileInfo.absoluteFilePath() ) ) {
qWarning() << "XdgBaseDirs::saveDir: failed to create directory '"
<< fileInfo.absoluteFilePath() << "'";
} else {
return fullPath;
}
}
return QString();
}
QString XdgBaseDirs::akonadiServerConfigFile( FileAccessMode openMode )
{
return akonadiConfigFile( QLatin1String( "akonadiserverrc" ), openMode );
}
QString XdgBaseDirs::akonadiConnectionConfigFile( FileAccessMode openMode )
{
return akonadiConfigFile( QLatin1String( "akonadiconnectionrc" ), openMode );
}
QString XdgBaseDirs::akonadiConfigFile( const QString &file, FileAccessMode openMode )
{
const QString akonadiDir = QLatin1String( "akonadi" );
const QString savePath = saveDir( "config", akonadiDir ) + QLatin1Char( '/' ) + file;
if ( openMode == WriteOnly ) {
return savePath;
}
const QString path = findResourceFile( "config", akonadiDir + QLatin1Char( '/' ) + file );
if ( path.isEmpty() ) {
return savePath;
} else if ( openMode == ReadOnly || path == savePath ) {
return path;
}
// file found in system paths and mode is ReadWrite, thus
// we copy to the home path location and return this path
QFile systemFile( path );
systemFile.copy( savePath );
return savePath;
}
QString XdgBaseDirsSingleton::homePath( const char *variable, const char *defaultSubDir )
{
const QByteArray env = qgetenv( variable );
QString xdgPath;
if ( env.isEmpty() ) {
xdgPath = QDir::homePath() + QLatin1Char( '/' ) + QLatin1String( defaultSubDir );
#if defined(Q_OS_WIN) //krazy:exclude=cpp
} else if ( QDir::isAbsolutePath( QString::fromLocal8Bit( env ) ) ) {
#else
} else if ( env.startsWith( '/' ) ) {
#endif
xdgPath = QString::fromLocal8Bit( env );
} else {
xdgPath = QDir::homePath() + QLatin1Char( '/' ) + QString::fromLocal8Bit( env );
}
return xdgPath;
}
QStringList XdgBaseDirsSingleton::systemPathList( const char *variable, const char *defaultDirList )
{
const QByteArray env = qgetenv( variable );
QString xdgDirList;
if ( env.isEmpty() ) {
xdgDirList = QLatin1String( defaultDirList );
} else {
xdgDirList = QString::fromLocal8Bit( env );
}
return splitPathList( xdgDirList );
}

View file

@ -0,0 +1,322 @@
/***************************************************************************
* Copyright (C) 2007 by Kevin Krammer <kevin.krammer@gmx.at> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Library General Public License as *
* published by the Free Software Foundation; either version 2 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 Library General Public *
* License along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#ifndef XDGBASEDIRS_H
#define XDGBASEDIRS_H
// Qt includes
#include <QtCore/QFlags>
#include <QtCore/QStringList>
#include "akonadiprotocolinternals_export.h"
// forward declarations
class QString;
namespace Akonadi {
class XdgBaseDirsPrivate;
/**
@brief Resource type based handling of standard directories
Developers of several Free Software desktop projects have created
a specification for handling so-called "base directories", i.e.
lists of system wide directories and directories within each user's
home directory for installing and later finding certain files.
This class handles the respective behaviour, i.e. environment variables
and their defaults, for the following type of resources:
- "config"
- "data"
Example: getting the Akonadi server config file "akonadiserverrc", assuming
that Akonadi stores its config in an additional subdirectoy called "akonadi"
@code
QString relativeFileName = QLatin1String( "akonadi/akonadiserverrc" );
// look for the file "akonadiserverrc" with additional subdirectory "akonadi"
// in any directory associated with resource type "config"
QString configFile = XdgBaseDirs::findResourceFile( "config", relativeFileName );
if ( configFile.isEmpty() ) {
// No config file yet, get the suitable user specific directory for storing
// a new one
configFile = XdgBaseDirs::saveDir( "config", QLatin1String( "akonadi" ) );
configFile += QLatin1String( "akonadiserverrc" );
}
QSettings serverConfig( configFile );
@endcode
@author Kevin Krammer, <kevin.krammer@gmx.at>
@see http://www.freedesktop.org/wiki/Specifications/basedir-spec
*/
class AKONADIPROTOCOLINTERNALS_EXPORT XdgBaseDirs
{
public:
/**
@brief Creates the instance
*/
XdgBaseDirs();
/**
@brief Destroys the instance
*/
~XdgBaseDirs();
/**
@brief Returns the user specific directory for the given resource type
Unless the user's environment has a specific path set as an override
this will be the default as defined in the freedesktop.org base-dir-spec
@note Caches the value of the first call
@param resource a named resource type, e.g. "config"
@return a directory path
@see systemPathList()
@see saveDir()
*/
static QString homePath( const char *resource );
/**
@brief Returns the list of system wide directories for a given resource type
The returned list can contain one or more directory paths. If there are more
than one, the list is sorted by falling priority, i.e. if an entry is valid
for the respective use case (e.g. contains a file the application looks for)
the list should not be processed further.
@note The user's resource path should, to be compliant with the spec,
always be treated as having higher priority than any path in the
list of system wide paths
@note Caches the value of the first call
@param resource a named resource type, e.g. "config"
@return a priority sorted list of directory paths
@see homePath()
*/
static QStringList systemPathList( const char *resource );
/**
@brief Searches the resource specific directories for a given file
Convenience method for finding a given file (with optional relative path)
in any of the configured base directories for a given resource type.
Will check the user local directory first and then process the system
wide path list according to the inherent priority.
@param resource a named resource type, e.g. "config"
@param relPath relative path of a file to look for,
e.g."akonadi/akonadiserverrc"
@returns the file path of the first match, or @c QString() if no such
relative path exists in any of the base directories or if
a match is not a file
@see findResourceDir()
@see saveDir
*/
static QString findResourceFile( const char *resource, const QString &relPath );
/**
@brief Searches the executable specific directories for a given file
Convenience method for finding a given executable (with optional relative path)
in any of the configured directories for a this special type.
@note This is not based on the XDG base dir spec, since it does not cover
executable
@param relPath relative path of a file to look for,
e.g."akonadiserver"
@param searchPath additional paths to search for the executable,
only used if the file was not found in PATH and the install prefix
@returns the file path of the first match, or @c QString() if no such
relative path exists in any of the base directories
@see findResourceFile()
*/
static QString findExecutableFile( const QString &relPath, const QStringList &searchPath = QStringList() );
/**
@brief Searches the plugin specific directories for a given file
Convenience method for finding a given plugin (with optional relative path)
in any of the configured directories for a this special type.
@note This is not based on the XDG base dir spec, since it does not cover
plugins
@param relPath relative path of a file to look for,
e.g."akonadi_knut_resource"
@param searchPath additional paths to search for the plugin,
only used if the file was not found in QT_PLUGIN_PATH and the install prefix
@returns the file path of the first match, or @c QString() if no such
relative path exists in any of the base directories
@see findResourceFile()
*/
static QString findPluginFile( const QString &relPath, const QStringList &searchPath = QStringList() );
/**
@brief Returns plugin specific directories
Convenience method for listing directories that can be scanned for available
plugins.
@note This is not based on the XDG base dir spec, since it does not cover
plugins.
@return directories where application should look for plugins
*/
static QStringList findPluginDirs();
/**
@brief Searches the resource specific directories for a given subdirectory
Convenience method for finding a given relative subdirectory in any of
the configured base directories for a given resource type.
Will check the user local directory first and then process the system
wide path list according to the inherent priority.
Use findAllResourceDirs() if looking for all directories with the given
subdirectory.
@param resource a named resource type, e.g. "config"
@param relPath relative path of a subdirectory to look for,
e.g."akonadi/agents"
@returns the directory path of the first match, or @c QString() if no such
relative path exists in any of the base directories or if
a match is not a directory
@see findResourceFile()
@see saveDir()
*/
static QString findResourceDir( const char *resource, const QString &relPath );
/**
@brief Searches the resource specific directories for a given subdirectory
Convenience method for getting a list of directoreis with a given relative
subdirectory in any of the configured base directories for a given
resource type.
Will check the user local directory first and then process the system
wide path list according to the inherent priority.
Similar to findResourceDir() but does not just find the first best match
but all matching resource directories. The resuling list will be sorted
according to the same proprity criteria.
@param resource a named resource type, e.g. "config"
@param relPath relative path of a subdirectory to look for,
e.g."akonadi/agents"
@returns a list of directory paths, or @c QString() if no such
relative path exists in any of the base directories or if
non of the matches is a directory
@see findResourceDir()
*/
static QStringList findAllResourceDirs( const char *resource, const QString &relPath );
/**
@brief Finds or creates the "save to" directory for a given resource
Convenience method for creating subdirectores relative to a given
resource type's user directory, i.e. homePath() + relPath
If the target directory does not exists, it an all necessary parent
directories will be created, unless denied by the filesystem.
@param resource a named resource type, e.g. "config"
@param relPath relative path of a directory to be used for file writing
@return the directory path of the "save to" directory or @c QString()
if the directory or one of its parents could not be created
@see findResourceDir()
*/
static QString saveDir( const char *resource, const QString &relPath );
/**
* @brief Open mode flags for resource files
*
* FileAccessMode is a typedef for QFlags<FileAccessFlag>. It stores
* a OR combination of FileAccessFlag values
*/
enum FileAccessFlag {
ReadOnly = 0x1,
WriteOnly = 0x2,
ReadWrite = ReadOnly | WriteOnly
};
typedef QFlags<FileAccessFlag> FileAccessMode;
/**
* @brief Returns the path of the Akonadi server config file
*
* Convenience method for getting the server config file "akonadiserverrc"
* since this is an often needed procedure in several parts of the code.
*
* @param openMode how the application wants to use the config file
*
* @return the path of the server config file, suitable for \p openMode
*/
static QString akonadiServerConfigFile( FileAccessMode openMode = ReadOnly );
/**
* @brief Returns the path of the Akonadi data connection config file
*
* Convenience method for getting the server config file "akonadiconnectionrc"
* since this is an often needed procedure in several parts of the code.
*
* @param openMode how the application wants to use the config file
*
* @return the path of the data connection config file, suitable for \p openMode
*/
static QString akonadiConnectionConfigFile( FileAccessMode openMode = ReadOnly );
private:
XdgBaseDirsPrivate *const d;
private:
static QString akonadiConfigFile( const QString &file, FileAccessMode openMode );
private:
XdgBaseDirs( const XdgBaseDirs & );
XdgBaseDirs &operator=( const XdgBaseDirs & );
};
}
#endif

View file

@ -0,0 +1 @@
# this directory will not be tested.

View file

@ -0,0 +1,46 @@
set(QSqlite_SRCS
src/sqlite_blocking.cpp
src/qsql_sqlite.cpp
src/smain.cpp
)
message(STATUS "Building QSQLITE3 driver")
if(INSTALL_QSQLITE_IN_QT_PREFIX)
set(QSQLITE_INSTALL_PREFIX "${QT_PLUGINS_DIR}/sqldrivers")
else()
set(QSQLITE_INSTALL_PREFIX "${LIB_INSTALL_DIR}/plugins/sqldrivers")
endif()
add_definitions(-Wall)
add_definitions(${QT_DEFINITIONS})
add_definitions(-DQT_PLUGIN)
add_definitions(-DQT_SHARED)
include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/src
${SQLITE_INCLUDE_DIR}
)
if(AKONADI_STATIC_SQLITE)
add_definitions(-DQT_STATICPLUGIN)
add_library(qsqlite3 STATIC ${QSqlite_SRCS} ${QSqlite_MOC_SRCS})
else()
add_library(qsqlite3 SHARED ${QSqlite_SRCS} ${QSqlite_MOC_SRCS})
endif()
target_link_libraries(qsqlite3 ${QT_QTCORE_LIBRARY} ${QT_QTSQL_LIBRARY})
if(SQLITE_LINK_STATIC)
message(STATUS "SQlite ${SQLITE_STATIC_LIBRARIES}")
target_link_libraries(qsqlite3 ${SQLITE_STATIC_LIBRARIES})
else()
message(STATUS "SQlite ${SQLITE_LIBRARIES}")
target_link_libraries(qsqlite3 ${SQLITE_LIBRARIES})
endif()
INSTALL(TARGETS qsqlite3
RUNTIME DESTINATION ${QSQLITE_INSTALL_PREFIX}
LIBRARY DESTINATION ${QSQLITE_INSTALL_PREFIX}
ARCHIVE DESTINATION ${QSQLITE_INSTALL_PREFIX}
)

3
akonadi/qsqlite/README Normal file
View file

@ -0,0 +1,3 @@
This is a sliglty adjusted version of the QSQLITE driver. Install this driver
somewhere in the QT_PLUGIN_PATH and use it in akonadi by setting the driver
to QSQLITE3.

View file

@ -0,0 +1,100 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtSql module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial Usage
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QSQLCACHEDRESULT_P_H
#define QSQLCACHEDRESULT_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of other Qt classes. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include "QtSql/qsqlresult.h"
QT_BEGIN_NAMESPACE
class QVariant;
template <typename T> class QVector;
class QSqlCachedResultPrivate;
class Q_SQL_EXPORT QSqlCachedResult: public QSqlResult
{
public:
virtual ~QSqlCachedResult();
typedef QVector<QVariant> ValueCache;
protected:
QSqlCachedResult(const QSqlDriver * db);
void init(int colCount);
void cleanup();
void clearValues();
virtual bool gotoNext(ValueCache &values, int index) = 0;
QVariant data(int i);
bool isNull(int i);
bool fetch(int i);
bool fetchNext();
bool fetchPrevious();
bool fetchFirst();
bool fetchLast();
int colCount() const;
ValueCache &cache();
void virtual_hook(int id, void *data);
private:
bool cacheNext();
QSqlCachedResultPrivate *d;
};
QT_END_NAMESPACE
#endif // QSQLCACHEDRESULT_P_H

View file

@ -0,0 +1,724 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtSql module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial Usage
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qsql_sqlite.h"
#include <qcoreapplication.h>
#include <qvariant.h>
#include <qsqlerror.h>
#include <qsqlfield.h>
#include <qsqlindex.h>
#include <qsqlquery.h>
#include <qstringlist.h>
#include <qvector.h>
#include <qdebug.h>
#if defined Q_OS_WIN
# include <qt_windows.h>
#else
# include <unistd.h>
#endif
#include <sqlite3.h>
#include <qthread.h>
#include "sqlite_blocking.h"
Q_DECLARE_METATYPE(sqlite3*)
Q_DECLARE_METATYPE(sqlite3_stmt*)
QT_BEGIN_NAMESPACE
static QString _q_escapeIdentifier(const QString &identifier)
{
QString res = identifier;
if(!identifier.isEmpty() && identifier.left(1) != QString(QLatin1Char('"')) && identifier.right(1) != QString(QLatin1Char('"')) ) {
res.replace(QLatin1Char('"'), QLatin1String("\"\""));
res.prepend(QLatin1Char('"')).append(QLatin1Char('"'));
res.replace(QLatin1Char('.'), QLatin1String("\".\""));
}
return res;
}
static QVariant::Type qGetColumnType(const QString &tpName)
{
const QString typeName = tpName.toLower();
if (typeName == QLatin1String("integer")
|| typeName == QLatin1String("int"))
return QVariant::Int;
if (typeName == QLatin1String("double")
|| typeName == QLatin1String("float")
|| typeName.startsWith(QLatin1String("numeric")))
return QVariant::Double;
if (typeName == QLatin1String("blob"))
return QVariant::ByteArray;
return QVariant::String;
}
static QSqlError qMakeError(sqlite3 *access, const QString &descr, QSqlError::ErrorType type,
int errorCode = -1)
{
return QSqlError(descr,
QString::fromUtf16(static_cast<const ushort *>(sqlite3_errmsg16(access))),
type, errorCode);
}
class QSQLiteDriverPrivate
{
public:
inline QSQLiteDriverPrivate() : access(0) {}
sqlite3 *access;
};
class QSQLiteResultPrivate
{
public:
QSQLiteResultPrivate(QSQLiteResult *res);
void cleanup();
bool fetchNext(QSqlCachedResult::ValueCache &values, int idx, bool initialFetch);
// initializes the recordInfo and the cache
void initColumns(bool emptyResultset);
void finalize();
QSQLiteResult* q;
sqlite3 *access;
sqlite3_stmt *stmt;
bool skippedStatus; // the status of the fetchNext() that's skipped
bool skipRow; // skip the next fetchNext()?
QSqlRecord rInf;
QVector<QVariant> firstRow;
};
QSQLiteResultPrivate::QSQLiteResultPrivate(QSQLiteResult* res) : q(res), access(0),
stmt(0), skippedStatus(false), skipRow(false)
{
}
void QSQLiteResultPrivate::cleanup()
{
finalize();
rInf.clear();
skippedStatus = false;
skipRow = false;
q->setAt(QSql::BeforeFirstRow);
q->setActive(false);
q->cleanup();
}
void QSQLiteResultPrivate::finalize()
{
if (!stmt)
return;
sqlite3_finalize(stmt);
stmt = 0;
}
void QSQLiteResultPrivate::initColumns(bool emptyResultset)
{
int nCols = sqlite3_column_count(stmt);
if (nCols <= 0)
return;
q->init(nCols);
for (int i = 0; i < nCols; ++i) {
QString colName = QString::fromUtf16(
static_cast<const ushort *>(sqlite3_column_name16(stmt, i))
).remove(QLatin1Char('"'));
// must use typeName for resolving the type to match QSqliteDriver::record
QString typeName = QString::fromUtf16(
static_cast<const ushort *>(sqlite3_column_decltype16(stmt, i)));
int dotIdx = colName.lastIndexOf(QLatin1Char('.'));
QSqlField fld(colName.mid(dotIdx == -1 ? 0 : dotIdx + 1), qGetColumnType(typeName));
// sqlite3_column_type is documented to have undefined behavior if the result set is empty
int stp = emptyResultset ? -1 : sqlite3_column_type(stmt, i);
fld.setSqlType(stp);
rInf.append(fld);
}
}
bool QSQLiteResultPrivate::fetchNext(QSqlCachedResult::ValueCache &values, int idx, bool initialFetch)
{
int res;
int i;
if (skipRow) {
// already fetched
Q_ASSERT(!initialFetch);
skipRow = false;
for(int i=0;i<firstRow.count();i++)
values[i]=firstRow[i];
return skippedStatus;
}
skipRow = initialFetch;
if(initialFetch) {
firstRow.clear();
firstRow.resize(sqlite3_column_count(stmt));
}
if (!stmt) {
q->setLastError(QSqlError(QCoreApplication::translate("QSQLiteResult", "Unable to fetch row"),
QCoreApplication::translate("QSQLiteResult", "No query"), QSqlError::ConnectionError));
q->setAt(QSql::AfterLastRow);
return false;
}
res = sqlite3_blocking_step(stmt);
switch(res) {
case SQLITE_ROW:
// check to see if should fill out columns
if (rInf.isEmpty())
// must be first call.
initColumns(false);
if (idx < 0 && !initialFetch)
return true;
for (i = 0; i < rInf.count(); ++i) {
switch (sqlite3_column_type(stmt, i)) {
case SQLITE_BLOB:
values[i + idx] = QByteArray(static_cast<const char *>(
sqlite3_column_blob(stmt, i)),
sqlite3_column_bytes(stmt, i));
break;
case SQLITE_INTEGER:
values[i + idx] = sqlite3_column_int64(stmt, i);
break;
case SQLITE_FLOAT:
switch(q->numericalPrecisionPolicy()) {
case QSql::LowPrecisionInt32:
values[i + idx] = sqlite3_column_int(stmt, i);
break;
case QSql::LowPrecisionInt64:
values[i + idx] = sqlite3_column_int64(stmt, i);
break;
case QSql::LowPrecisionDouble:
case QSql::HighPrecision:
default:
values[i + idx] = sqlite3_column_double(stmt, i);
break;
};
break;
case SQLITE_NULL:
values[i + idx] = QVariant(QVariant::String);
break;
default:
values[i + idx] = QString::fromUtf16(static_cast<const ushort *>(
sqlite3_column_text16(stmt, i)),
sqlite3_column_bytes16(stmt, i) / sizeof(ushort));
break;
}
}
return true;
case SQLITE_DONE:
if (rInf.isEmpty())
// must be first call.
initColumns(true);
q->setAt(QSql::AfterLastRow);
sqlite3_reset(stmt);
return false;
case SQLITE_ERROR:
// SQLITE_ERROR is a generic error code and we must call sqlite3_reset()
// to get the specific error message.
res = sqlite3_reset(stmt);
q->setLastError(qMakeError(access, QCoreApplication::translate("QSQLiteResult",
"Unable to fetch row"), QSqlError::ConnectionError, res));
q->setAt(QSql::AfterLastRow);
return false;
case SQLITE_MISUSE:
case SQLITE_BUSY:
default:
// something wrong, don't get col info, but still return false
q->setLastError(qMakeError(access, QCoreApplication::translate("QSQLiteResult",
"Unable to fetch row"), QSqlError::ConnectionError, res));
sqlite3_reset(stmt);
q->setAt(QSql::AfterLastRow);
return false;
}
return false;
}
QSQLiteResult::QSQLiteResult(const QSQLiteDriver* db)
: QSqlCachedResult(db)
{
d = new QSQLiteResultPrivate(this);
d->access = db->d->access;
}
QSQLiteResult::~QSQLiteResult()
{
d->cleanup();
delete d;
}
void QSQLiteResult::virtual_hook(int id, void *data)
{
switch (id) {
case QSqlResult::DetachFromResultSet:
if (d->stmt)
sqlite3_reset(d->stmt);
break;
default:
QSqlCachedResult::virtual_hook(id, data);
}
}
bool QSQLiteResult::reset(const QString &query)
{
if (!prepare(query))
return false;
return exec();
}
bool QSQLiteResult::prepare(const QString &query)
{
if (!driver() || !driver()->isOpen() || driver()->isOpenError())
return false;
d->cleanup();
setSelect(false);
#if (SQLITE_VERSION_NUMBER >= 3003011)
// int res = sqlite3_prepare16_v2(d->access, query.constData(), (query.size() + 1) * sizeof(QChar),
// &d->stmt, 0);
int res = sqlite3_blocking_prepare16_v2(d->access, query.constData(), (query.size() + 1) * sizeof(QChar),
&d->stmt, 0);
#else
int res = sqlite3_prepare16(d->access, query.constData(), (query.size() + 1) * sizeof(QChar),
&d->stmt, 0);
#endif
if (res != SQLITE_OK) {
setLastError(qMakeError(d->access, QCoreApplication::translate("QSQLiteResult",
"Unable to execute statement"), QSqlError::StatementError, res));
d->finalize();
return false;
}
return true;
}
bool QSQLiteResult::exec()
{
const QVector<QVariant> values = boundValues();
d->skippedStatus = false;
d->skipRow = false;
d->rInf.clear();
clearValues();
setLastError(QSqlError());
int res = sqlite3_reset(d->stmt);
if (res != SQLITE_OK) {
setLastError(qMakeError(d->access, QCoreApplication::translate("QSQLiteResult",
"Unable to reset statement"), QSqlError::StatementError, res));
d->finalize();
return false;
}
int paramCount = sqlite3_bind_parameter_count(d->stmt);
if (paramCount == values.count()) {
for (int i = 0; i < paramCount; ++i) {
res = SQLITE_OK;
const QVariant value = values.at(i);
if (value.isNull()) {
res = sqlite3_bind_null(d->stmt, i + 1);
} else {
switch (value.type()) {
case QVariant::ByteArray: {
const QByteArray *ba = static_cast<const QByteArray*>(value.constData());
res = sqlite3_bind_blob(d->stmt, i + 1, ba->constData(),
ba->size(), SQLITE_STATIC);
break; }
case QVariant::Int:
res = sqlite3_bind_int(d->stmt, i + 1, value.toInt());
break;
case QVariant::Double:
res = sqlite3_bind_double(d->stmt, i + 1, value.toDouble());
break;
case QVariant::UInt:
case QVariant::LongLong:
res = sqlite3_bind_int64(d->stmt, i + 1, value.toLongLong());
break;
case QVariant::String: {
// lifetime of string == lifetime of its qvariant
const QString *str = static_cast<const QString*>(value.constData());
res = sqlite3_bind_text16(d->stmt, i + 1, str->utf16(),
(str->size()) * sizeof(QChar), SQLITE_STATIC);
break; }
default: {
QString str = value.toString();
// SQLITE_TRANSIENT makes sure that sqlite buffers the data
res = sqlite3_bind_text16(d->stmt, i + 1, str.utf16(),
(str.size()) * sizeof(QChar), SQLITE_TRANSIENT);
break; }
}
}
if (res != SQLITE_OK) {
setLastError(qMakeError(d->access, QCoreApplication::translate("QSQLiteResult",
"Unable to bind parameters"), QSqlError::StatementError, res));
d->finalize();
return false;
}
}
} else {
setLastError(QSqlError(QCoreApplication::translate("QSQLiteResult",
"Parameter count mismatch"), QString(), QSqlError::StatementError));
return false;
}
d->skippedStatus = d->fetchNext(d->firstRow, 0, true);
if (lastError().isValid()) {
setSelect(false);
setActive(false);
return false;
}
setSelect(!d->rInf.isEmpty());
setActive(true);
return true;
}
bool QSQLiteResult::gotoNext(QSqlCachedResult::ValueCache& row, int idx)
{
return d->fetchNext(row, idx, false);
}
int QSQLiteResult::size()
{
return -1;
}
int QSQLiteResult::numRowsAffected()
{
return sqlite3_changes(d->access);
}
QVariant QSQLiteResult::lastInsertId() const
{
if (isActive()) {
qint64 id = sqlite3_last_insert_rowid(d->access);
if (id)
return id;
}
return QVariant();
}
QSqlRecord QSQLiteResult::record() const
{
if (!isActive() || !isSelect())
return QSqlRecord();
return d->rInf;
}
QVariant QSQLiteResult::handle() const
{
return qVariantFromValue(d->stmt);
}
/////////////////////////////////////////////////////////
QSQLiteDriver::QSQLiteDriver(QObject * parent)
: QSqlDriver(parent)
{
d = new QSQLiteDriverPrivate();
}
QSQLiteDriver::QSQLiteDriver(sqlite3 *connection, QObject *parent)
: QSqlDriver(parent)
{
d = new QSQLiteDriverPrivate();
d->access = connection;
setOpen(true);
setOpenError(false);
}
QSQLiteDriver::~QSQLiteDriver()
{
delete d;
}
bool QSQLiteDriver::hasFeature(DriverFeature f) const
{
switch (f) {
case BLOB:
case Transactions:
case Unicode:
case LastInsertId:
case PreparedQueries:
case PositionalPlaceholders:
case SimpleLocking:
case FinishQuery:
case LowPrecisionNumbers:
return true;
case QuerySize:
case NamedPlaceholders:
case BatchOperations:
case EventNotifications:
case MultipleResultSets:
return false;
}
return false;
}
static int qGetSqliteTimeout(QString opts)
{
enum { DefaultTimeout = 5000 };
opts.remove(QLatin1Char(' '));
Q_FOREACH(const QString &option, opts.split(QLatin1Char(';'))) {
if (option.startsWith(QLatin1String("QSQLITE_BUSY_TIMEOUT="))) {
bool ok;
int nt = option.mid(21).toInt(&ok);
if (ok)
return nt;
}
}
return DefaultTimeout;
}
static int qGetSqliteOpenMode(QString opts)
{
opts.remove(QLatin1Char(' '));
Q_FOREACH(const QString &option, opts.split(QLatin1Char(';'))) {
if (option == QLatin1String("QSQLITE_OPEN_READONLY"))
return SQLITE_OPEN_READONLY;
}
// The SQLITE_OPEN_NOMUTEX flag causes the database connection to be in the multi-thread mode
return SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_NOMUTEX | SQLITE_OPEN_SHAREDCACHE;
}
/*
SQLite dbs have no user name, passwords, hosts or ports.
just file names.
*/
bool QSQLiteDriver::open(const QString & db, const QString &, const QString &, const QString &, int, const QString &conOpts)
{
if (isOpen())
close();
if (db.isEmpty())
return false;
sqlite3_enable_shared_cache(1);
if (sqlite3_open_v2(db.toUtf8().constData(), &d->access, qGetSqliteOpenMode(conOpts), NULL) == SQLITE_OK) {
sqlite3_busy_timeout(d->access, qGetSqliteTimeout(conOpts));
sqlite3_extended_result_codes(d->access, 1);
setOpen(true);
setOpenError(false);
return true;
} else {
setLastError(qMakeError(d->access, tr("Error opening database"),
QSqlError::ConnectionError));
setOpenError(true);
return false;
}
}
void QSQLiteDriver::close()
{
if (isOpen()) {
if (sqlite3_close(d->access) != SQLITE_OK)
setLastError(qMakeError(d->access, tr("Error closing database"),
QSqlError::ConnectionError));
d->access = 0;
setOpen(false);
setOpenError(false);
}
}
QSqlResult *QSQLiteDriver::createResult() const
{
return new QSQLiteResult(this);
}
bool QSQLiteDriver::beginTransaction()
{
if (!isOpen() || isOpenError())
return false;
QSqlQuery q(createResult());
if (!q.exec(QLatin1String("BEGIN"))) {
setLastError(QSqlError(tr("Unable to begin transaction"),
q.lastError().databaseText(), QSqlError::TransactionError));
return false;
}
return true;
}
bool QSQLiteDriver::commitTransaction()
{
if (!isOpen() || isOpenError())
return false;
QSqlQuery q(createResult());
if (!q.exec(QLatin1String("COMMIT"))) {
setLastError(QSqlError(tr("Unable to commit transaction"),
q.lastError().databaseText(), QSqlError::TransactionError));
return false;
}
return true;
}
bool QSQLiteDriver::rollbackTransaction()
{
if (!isOpen() || isOpenError())
return false;
QSqlQuery q(createResult());
if (!q.exec(QLatin1String("ROLLBACK"))) {
setLastError(QSqlError(tr("Unable to rollback transaction"),
q.lastError().databaseText(), QSqlError::TransactionError));
return false;
}
return true;
}
QStringList QSQLiteDriver::tables(QSql::TableType type) const
{
QStringList res;
if (!isOpen())
return res;
QSqlQuery q(createResult());
q.setForwardOnly(true);
QString sql = QLatin1String("SELECT name FROM sqlite_master WHERE %1 "
"UNION ALL SELECT name FROM sqlite_temp_master WHERE %1");
if ((type & QSql::Tables) && (type & QSql::Views))
sql = sql.arg(QLatin1String("type='table' OR type='view'"));
else if (type & QSql::Tables)
sql = sql.arg(QLatin1String("type='table'"));
else if (type & QSql::Views)
sql = sql.arg(QLatin1String("type='view'"));
else
sql.clear();
if (!sql.isEmpty() && q.exec(sql)) {
while(q.next())
res.append(q.value(0).toString());
}
if (type & QSql::SystemTables) {
// there are no internal tables beside this one:
res.append(QLatin1String("sqlite_master"));
}
return res;
}
static QSqlIndex qGetTableInfo(QSqlQuery &q, const QString &tableName, bool onlyPIndex = false)
{
QString schema;
QString table(tableName);
int indexOfSeparator = tableName.indexOf(QLatin1Char('.'));
if (indexOfSeparator > -1) {
schema = tableName.left(indexOfSeparator).append(QLatin1Char('.'));
table = tableName.mid(indexOfSeparator + 1);
}
q.exec(QLatin1String("PRAGMA ") + schema + QLatin1String("table_info (") + _q_escapeIdentifier(table) + QLatin1String(")"));
QSqlIndex ind;
while (q.next()) {
bool isPk = q.value(5).toInt();
if (onlyPIndex && !isPk)
continue;
QString typeName = q.value(2).toString().toLower();
QSqlField fld(q.value(1).toString(), qGetColumnType(typeName));
if (isPk && (typeName == QLatin1String("integer")))
// INTEGER PRIMARY KEY fields are auto-generated in sqlite
// INT PRIMARY KEY is not the same as INTEGER PRIMARY KEY!
fld.setAutoValue(true);
fld.setRequired(q.value(3).toInt() != 0);
fld.setDefaultValue(q.value(4));
ind.append(fld);
}
return ind;
}
QSqlIndex QSQLiteDriver::primaryIndex(const QString &tblname) const
{
if (!isOpen())
return QSqlIndex();
QString table = tblname;
if (isIdentifierEscaped(table, QSqlDriver::TableName))
table = stripDelimiters(table, QSqlDriver::TableName);
QSqlQuery q(createResult());
q.setForwardOnly(true);
return qGetTableInfo(q, table, true);
}
QSqlRecord QSQLiteDriver::record(const QString &tbl) const
{
if (!isOpen())
return QSqlRecord();
QString table = tbl;
if (isIdentifierEscaped(table, QSqlDriver::TableName))
table = stripDelimiters(table, QSqlDriver::TableName);
QSqlQuery q(createResult());
q.setForwardOnly(true);
return qGetTableInfo(q, table);
}
QVariant QSQLiteDriver::handle() const
{
return qVariantFromValue(d->access);
}
QString QSQLiteDriver::escapeIdentifier(const QString &identifier, IdentifierType type) const
{
Q_UNUSED(type);
return _q_escapeIdentifier(identifier);
}
QT_END_NAMESPACE

View file

@ -0,0 +1,123 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtSql module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial Usage
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain
** additional rights. These rights are described in the Nokia Qt LGPL
** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
** package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://www.qtsoftware.com/contact.
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QSQL_SQLITE_H
#define QSQL_SQLITE_H
#include <QtSql/qsqldriver.h>
#include <QtSql/qsqlresult.h>
#include <QtSql/private/qsqlcachedresult_p.h>
struct sqlite3;
#ifdef QT_PLUGIN
#define Q_EXPORT_SQLDRIVER_SQLITE
#else
#define Q_EXPORT_SQLDRIVER_SQLITE Q_SQL_EXPORT
#endif
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
class QSQLiteDriverPrivate;
class QSQLiteResultPrivate;
class QSQLiteDriver;
class QSQLiteResult : public QSqlCachedResult
{
friend class QSQLiteDriver;
friend class QSQLiteResultPrivate;
public:
explicit QSQLiteResult(const QSQLiteDriver* db);
~QSQLiteResult();
QVariant handle() const;
protected:
bool gotoNext(QSqlCachedResult::ValueCache& row, int idx);
bool reset(const QString &query);
bool prepare(const QString &query);
bool exec();
int size();
int numRowsAffected();
QVariant lastInsertId() const;
QSqlRecord record() const;
void virtual_hook(int id, void *data);
private:
QSQLiteResultPrivate* d;
};
class Q_EXPORT_SQLDRIVER_SQLITE QSQLiteDriver : public QSqlDriver
{
Q_OBJECT
friend class QSQLiteResult;
public:
explicit QSQLiteDriver(QObject *parent = 0);
explicit QSQLiteDriver(sqlite3 *connection, QObject *parent = 0);
~QSQLiteDriver();
bool hasFeature(DriverFeature f) const;
bool open(const QString & db,
const QString & user,
const QString & password,
const QString & host,
int port,
const QString & connOpts);
void close();
QSqlResult *createResult() const;
bool beginTransaction();
bool commitTransaction();
bool rollbackTransaction();
QStringList tables(QSql::TableType) const;
QSqlRecord record(const QString& tablename) const;
QSqlIndex primaryIndex(const QString &table) const;
QVariant handle() const;
QString escapeIdentifier(const QString &identifier, IdentifierType) const;
private:
QSQLiteDriverPrivate* d;
};
QT_END_NAMESPACE
QT_END_HEADER
#endif // QSQL_SQLITE_H

View file

@ -0,0 +1,82 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial Usage
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain
** additional rights. These rights are described in the Nokia Qt LGPL
** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
** package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://www.qtsoftware.com/contact.
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtCore/QStringList>
#include <QtSql/QSqlDriverPlugin>
#include "qsql_sqlite.h"
QT_BEGIN_NAMESPACE
class QSQLiteDriverPlugin : public QSqlDriverPlugin
{
public:
QSQLiteDriverPlugin();
QSqlDriver* create(const QString &);
QStringList keys() const;
};
QSQLiteDriverPlugin::QSQLiteDriverPlugin()
: QSqlDriverPlugin()
{
}
QSqlDriver* QSQLiteDriverPlugin::create(const QString &name)
{
if (name == QLatin1String("QSQLITE3")) {
QSQLiteDriver* driver = new QSQLiteDriver();
return driver;
}
return 0;
}
QStringList QSQLiteDriverPlugin::keys() const
{
QStringList l;
l << QLatin1String("QSQLITE3");
return l;
}
Q_EXPORT_STATIC_PLUGIN(QSQLiteDriverPlugin)
Q_EXPORT_PLUGIN2(qsqlite3, QSQLiteDriverPlugin)
QT_END_NAMESPACE

Some files were not shown because too many files have changed in this diff Show more