import working copy of kdepim-runtime

This commit is contained in:
Ivailo Monev 2015-04-14 22:08:21 +00:00
parent df5deda5e5
commit 14fa9251ef
1533 changed files with 191508 additions and 0 deletions

View file

@ -30,4 +30,5 @@ macro_optional_add_subdirectory (kaffeine)
macro_optional_add_subdirectory (kamoso) macro_optional_add_subdirectory (kamoso)
macro_optional_add_subdirectory (kcachegrind) macro_optional_add_subdirectory (kcachegrind)
macro_optional_add_subdirectory (kdepimlibs) macro_optional_add_subdirectory (kdepimlibs)
macro_optional_add_subdirectory (kdepim-runtime)
macro_optional_add_subdirectory (kdepim) macro_optional_add_subdirectory (kdepim)

View file

@ -0,0 +1,212 @@
project(kdepim-runtime)
# where to look first for cmake modules. This line must be the first one or cmake will use the system's FindFoo.cmake
set(CMAKE_MODULE_PATH ${kdepim-runtime_SOURCE_DIR}/cmake/modules)
############### KDEPIM-Runtime version ################
# KDEPIM_RUNTIME_VERSION
# Version scheme: "x.y.z build".
#
# x is the version number.
# y is the major release number.
# z is the minor release number.
#
# "x.y.z" follow the kdelibs version kdepim is released with.
#
# If "z" is 0, it the version is "x.y"
#
# KDEPIM_RUNTIME_DEV_VERSION
# is empty for final versions. For development versions "build" is
# something like "pre", "alpha1", "alpha2", "beta1", "beta2", "rc1", "rc2".
#
# Examples in chronological order:
#
# 3.0
# 3.0.1
# 3.1 alpha1
# 3.1 beta1
# 3.1 beta2
# 3.1 rc1
# 3.1
# 3.1.1
# 3.2 pre
# 3.2 alpha1
if(NOT DEFINED KDEPIM_RUNTIME_DEV_VERSION)
set(KDEPIM_RUNTIME_DEV_VERSION "")
endif()
set(KDEPIM_RUNTIME_VERSION "4.14.3${KDEPIM_RUNTIME_DEV_VERSION}")
configure_file(kdepim-runtime-version.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/kdepim-runtime-version.h @ONLY)
############### search-related options ################
add_definitions(-DQT_USE_QSTRINGBUILDER)
############### search packages used by KDE ###############
set(CMAKE_AUTOMOC ON)
# Kdelibs
find_package(KDE4 4.13.0 REQUIRED)
include(KDE4Defaults)
# KdepimLibs
find_package(KdepimLibs 4.14.3)
set_package_properties(KdepimLibs PROPERTIES DESCRIPTION "The KDEPIM libraries" URL "http://www.kde.org" TYPE REQUIRED)
#Boost
# Don't use BoostConfig.cmake
set(Boost_NO_BOOST_CMAKE TRUE)
find_package(Boost 1.34.0)
set_package_properties(Boost PROPERTIES DESCRIPTION "Boost C++ Libraries" URL "http://www.boost.org" TYPE REQUIRED PURPOSE "Boost is required by Akonadi")
# Akonadi
find_package(Akonadi 1.12.90 QUIET CONFIG)
set_package_properties(Akonadi PROPERTIES DESCRIPTION "Akonadi server libraries" URL "http://pim.kde.org/akonadi" TYPE REQUIRED PURPOSE "Access to PIM storage and services")
# shared-mime-info
find_package(SharedMimeInfo 0.30)
set_package_properties(SharedMimeInfo PROPERTIES DESCRIPTION "The shared-mime-info utility" URL "http://freedesktop.org/wiki/Software/shared-mime-info" TYPE REQUIRED PURPOSE "Information about filetypes")
# Libkolab
find_package(Libkolab 0.5.2 QUIET CONFIG)
set_package_properties(Libkolab PROPERTIES DESCRIPTION "libkolab" URL "http://mirror.kolabsys.com/pub/releases" TYPE OPTIONAL PURPOSE "The Kolab Format libraries are required to build the Kolab Groupware Resource")
# Libkolabxml
find_package(Libkolabxml 1.0 QUIET CONFIG)
set_package_properties(Libkolabxml PROPERTIES DESCRIPTION "Kolabxml" URL "http://mirror.kolabsys.com/pub/releases" TYPE OPTIONAL PURPOSE "The Kolab XML Format Schema Definitions Library is required to build the Kolab Groupware Resource")
# Libkgapi2
find_package(LibKGAPI2 2.2.0 QUIET CONFIG)
set_package_properties(LibKGAPI2 PROPERTIES DESCRIPTION "KDE-based library for accessing various Google services" URL "https://projects.kde.org/libkgapi" TYPE OPTIONAL PURPOSE "LibKGAPI is required to build Akonadi resources to access Google Contacts, Calendars and Tasks and Gmail")
# Libkfbapi
find_package(LibKFbAPI 1.0 QUIET CONFIG)
set_package_properties(LibKFbAPI PROPERTIES DESCRIPTION "A library to access Facebook services" URL "http://projects.kde.org/libkfbapi" TYPE OPTIONAL PURPOSE "LibKFbAPI is required to build Akonadi resources to access Facebook's contacts, events, notes and posts" )
if(LibKGAPI2_FOUND OR LibKFbAPI_FOUND)
find_package(QJSON)
set_package_properties(QJSON PROPERTIES DESCRIPTION "Qt library for handling JSON data" URL "http://qjson.sourceforge.net/" TYPE REQUIRED PURPOSE "Required to build the Google and Facebook resources")
endif()
# Xsltproc
find_package(Xsltproc)
set_package_properties(Xsltproc PROPERTIES DESCRIPTION "XSLT processor from libxslt" TYPE REQUIRED PURPOSE "Required to generate D-Bus interfaces for all Akonadi resources.")
find_package(AccountsQt 1.11 QUIET CONFIG)
set_package_properties(AccountsQt PROPERTIES DESCRIPTION "Qt bindings for accounts-sso" URL "https://code.google.com/p/accounts-sso/" TYPE OPTIONAL PURPOSE "Required to support AccountsQt in different resources")
find_package(SignOnQt 8.56 QUIET CONFIG)
set_package_properties(SignOnQt PROPERTIES DESCRIPTION "SignOn Qt bindings for accounts-sso" URL "https://code.google.com/p/accounts-sso/" TYPE OPTIONAL PURPOSE "Required to support SignOn in different resources")
############### Load the CTest options ###############
# CMake is irritating and doesn't allow setting the tests timeout globally.
# Let's work around this. The global timeout is now 2 minutes.
set(_DartConfigFile "${CMAKE_BINARY_DIR}/DartConfiguration.tcl")
if(EXISTS ${_DartConfigFile})
set(DartTestingTimeout "120")
file(READ ${_DartConfigFile} _DartConfigFile_content)
string(REGEX REPLACE "TimeOut: 1500" "TimeOut: ${DartTestingTimeout}" _DartConfigFile_content ${_DartConfigFile_content})
file(WRITE ${_DartConfigFile} ${_DartConfigFile_content})
endif()
# 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)
option(KDEPIM_RUN_ISOLATED_TESTS "Run the isolated tests." FALSE)
############### Desktop vs. Mobile options ##############
option(KDEPIM_MOBILE_UI "Build UI for mobile devices instead of for desktops" FALSE)
if (KDEPIM_MOBILE_UI)
add_definitions( -DKDEPIM_MOBILE_UI )
if(NOT QT_QTDECLARATIVE_FOUND)
message(FATAL_ERROR "The QtDeclarative library is required for building the mobile UI")
endif()
endif ()
set(LIBRARY_TYPE SHARED)
#FIXME: kde4_add_plugin doesn't have a parameter to build the plugins statically.
if (RUNTIME_PLUGINS_STATIC)
set(SERIALIZER_TYPE STATIC)
endif ()
############### Enterprise build options #################
option(KDEPIM_ENTERPRISE_BUILD "Enable features specific to the enterprise branch, which are normally disabled. Also, it disables many components not needed for Kontact such as the Kolab client." FALSE)
# config-enterprise.h is needed for both ENTERPRISE_BUILD and BUILD_EVERYTHING
configure_file(config-enterprise.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-enterprise.h )
############### Needed commands before building anything ###############
include_directories(${kdepim-runtime_SOURCE_DIR} ${kdepim-runtime_BINARY_DIR} ${KDEPIMLIBS_INCLUDE_DIRS} ${AKONADI_INCLUDE_DIR} ${KDE4_INCLUDES} ${Boost_INCLUDE_DIR})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${KDE4_ENABLE_EXCEPTIONS}")
############### Generate akonadi-config.h ###############
configure_file(akonadi-version.h.cmake "${kdepim-runtime_BINARY_DIR}/akonadi-version.h" @ONLY)
############### Macros ###############
# resource tests
macro( akonadi_add_resourcetest _testname _script )
if ( ${EXECUTABLE_OUTPUT_PATH} )
set( _exepath ${EXECUTABLE_OUTPUT_PATH} )
else ()
set( _exepath ${kdepim-runtime_BINARY_DIR}/resourcetester )
endif ()
if (WIN32)
set(_resourcetester ${_exepath}/resourcetester.bat)
else ()
set(_resourcetester ${_exepath}/resourcetester)
endif ()
if (UNIX)
set(_resourcetester ${_resourcetester}.shell)
endif ()
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/${_script} ${CMAKE_CURRENT_BINARY_DIR}/${_script} COPYONLY)
if (KDEPIM_RUN_ISOLATED_TESTS)
add_test( akonadi-mysql-db-${_testname} akonaditest -c ${kdepim-runtime_SOURCE_DIR}/resourcetester/tests/unittestenv/config-mysql-db.xml ${_resourcetester} -c ${CMAKE_CURRENT_BINARY_DIR}/${_script} )
endif ()
endmacro( akonadi_add_resourcetest )
############### Now, we add the components ###############
add_subdirectory(resources)
add_subdirectory(agents)
add_subdirectory(libkdepim-copy)
add_subdirectory(plugins)
add_subdirectory(accountwizard)
add_subdirectory(defaultsetup)
add_subdirectory(resourcetester)
add_subdirectory(kioslave)
add_subdirectory(kcm)
add_subdirectory(tray)
add_subdirectory(migration)
if (KDEPIMLIBS_KRESOURCES_LIBS)
add_subdirectory(kresources)
endif ()
if (QT_QTDECLARATIVE_FOUND)
add_subdirectory(qml)
endif ()
#if(OPENSYNC_FOUND)
# add_subdirectory(opensync)
#endif(OPENSYNC_FOUND)
############### Here we install some extra stuff ###############
## install the MIME type spec file for KDEPIM specific MIME types
install(FILES kdepim-mime.xml DESTINATION ${XDG_MIME_INSTALL_DIR})
update_xdg_mimetypes(${XDG_MIME_INSTALL_DIR})
feature_summary(WHAT ALL
INCLUDE_QUIET_PACKAGES
FATAL_ON_MISSING_REQUIRED_PACKAGES
)

346
kdepim-runtime/COPYING Normal file
View file

@ -0,0 +1,346 @@
NOTE! The GPL below is copyrighted by the Free Software Foundation, but
the instance of code that it refers to (the kde programs) are copyrighted
by the authors who actually wrote it.
---------------------------------------------------------------------------
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19yy name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

510
kdepim-runtime/COPYING.LIB Normal file
View file

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

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 "kdepim-runtime")
set(CTEST_NIGHTLY_START_TIME "20:00:00 CET")
set(CTEST_DROP_METHOD "http")
set(CTEST_DROP_SITE "my.cdash.org")
set(CTEST_DROP_LOCATION "/submit.php?project=kdepim-runtime")
set(CTEST_DROP_SITE_CDASH TRUE)

View file

@ -0,0 +1,31 @@
# 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 2000)
# Warnings that will be ignored
set(CTEST_CUSTOM_WARNING_EXCEPTION
"too big, try a different debug format"
"qlist.h.*increases required alignment of target type"
"qmap.h.*increases required alignment of target type"
"qhash.h.*increases required alignment of target type"
".*warning.* is deprecated"
)
# Errors that will be ignored
set(CTEST_CUSTOM_ERROR_EXCEPTION
"ICECC"
"Segmentation fault"
"Error 1 (ignored)"
"invoking macro kDebug argument 1"
"GConf Error"
"Client failed to connect to the D-BUS daemon"
"Failed to connect to socket"
)
# No coverage for these files
set(CTEST_CUSTOM_COVERAGE_EXCLUDE ".moc$" "moc_" "ui_" "ontologies")

105
kdepim-runtime/Mainpage.dox Normal file
View file

@ -0,0 +1,105 @@
/**
\mainpage Akonadi, the KDE PIM storage framework
These pages are a combination of design and api documentation. If you are
looking for general information go to the Overview section.
For detailed information and/or api-dox on any of the packages go to the
package main page, either from the menu on the left or from the Building
blocks section below.
\section akonadi_overview Overview
- Design and Concepts
- \ref akonadi_design_communication
- \ref akonadi_usage
- <a href="http://pim.kde.org/akonadi">Website</a>
- <a href="http://techbase.kde.org/index.php?title=Projects/PIM/Akonadi">Wiki</a>
- \ref akonadi_todos
\section akonadi_building_blocks Building Blocks
- Domain-specific libraries:
- <a href="../../kdepimlibs-apidocs/kabc/html/index.html">Contacts (KABC)</a>
- <a href="../../kdepimlibs-apidocs/kmime/html/index.html">MIME Messages (KMime)</a>
- <a href="../../kdepimlibs-apidocs/kcal/html/index.html">Events, todo items and journal entries (KCal)</a>
- <a href="../../kdepimlibs-apidocs/akonadi/html/index.html">Core library (libakonadi)</a>
\authors Tobias König <tokoe@kde.org>, Volker Krause <vkrause@kde.org>
\licenses \lgpl
*/
/**
\page akonadi_design_communication Communication Schemas
\section akonadi_design_communication_search Search
The sequence diagrams below show how general communication is done:
<div id='akonadi_client_search_small.png' onClick="document.getElementById('akonadi_client_search_small.png').style.display='none';document.getElementById(' akonadi_client_search.png').style.display='inline';" title="Click to enlarge" >
\image html akonadi_client_search_small.png "Akonadi Communication Schema"
</div>
<div id=' akonadi_client_search.png' onClick="document.getElementById(' akonadi_client_search.png').style.display='none';document.getElementById('akonadi_client_search_small.png').style.display='inline';" style="display:none" >
\image html akonadi_client_search.png "Akonadi Communication Schema"
</div>
\image latex akonadi_client_search.eps "Akonadi Communication Schema" height=5cm
The item search request is probably the call which is used most often
by the clients (components or applications). This call enables the client
to search for a list of items of a given mime type which match a
given search criterion.
In this case the client will contact the SearchProvider responsible for
the mime type, in order to retrieve the list of matching UIDs. The SearchProvider
already has a list of all available items of this mime type in its memory, so it
can search fast and use indices for optimization.
To communicate mime type constraints in FETCH and LIST and their responses the
IMAP flags mechanism is used. Unknown flags should be ignored by non-Akonadi
IMAP clients, which keeps compatibility with mutt and regular KMail.
Examples:
- List
\verbatim
0x8053c68 8 LIST "" "res1/foo/%"
0x8053c68 * LIST (\MimeTypes[text/calendar,directory/inode]) "/" "res1/foo/bar"
\endverbatim
- Fetch
\verbatim
0x8056310 7 UID FETCH 22 (UID RFC822.SIZE FLAGS BODY.PEEK[])
0x8056310 * 1 FETCH (FLAGS (\Seen \MimeTypes[message/rfc822]) RFC822 {2450} From: Till Adam To: ...
\endverbatim
\section akonadi_design_communication_agent Agent Handling
<div id=' akonadi_agent_handling_small.png' onClick="document.getElementById(' akonadi_agent_handling_small.png').style.display='none';document.getElementById(' akonadi_agent_handling.png').style.display='inline';" title="Click to enlarge" >
\image html akonadi_agent_handling_small.png "Akonadi Agent Handling"
</div>
<div id=' akonadi_agent_handling.png' onClick="document.getElementById(' akonadi_agent_handling.png').style.display='none';document.getElementById(' akonadi_agent_handling_small.png').style.display='inline';" style="display:none" >
\image html akonadi_agent_handling.png "Akonadi Agent Handling"
</div>
\image latex akonadi_agent_handling.eps "Akonadi Agent Handling" height=4cm
*/
/**
\page akonadi_overview_uml Akonadi Overview
This overview does not show a complete class or collaboration diagram, it is rather meant to show the
big picture.
<div id=' akonadi_overview_uml_small.png' onClick="document.getElementById(' akonadi_overview_uml_small.png').style.display='none';document.getElementById(' akonadi_overview_uml.png').style.display='inline';" title="Click to enlarge" >
\image html akonadi_overview_uml_small.png "Akonadi Overview"
</div>
<div id=' akonadi_overview_uml.png' onClick="document.getElementById(' akonadi_overview_uml.png').style.display='none';document.getElementById(' akonadi_overview_uml_small.png').style.display='inline';" style="display:none" >
\image html akonadi_overview_uml.png "Akonadi Overview"
</div>
*/
// DOXYGEN_NAME=kdepim-runtime
// DOXYGEN_ENABLE=YES

3
kdepim-runtime/README Normal file
View file

@ -0,0 +1,3 @@
The KDE project kdepim-runtime contains the Akonadi resources from kdepim which can be used without the applications in kdepim.
Here is the online code-repostitory of kdepim-runtime: http://quickgit.kde.org/?p=kdepim-runtime.git&a=summary

View file

@ -0,0 +1,71 @@
add_definitions( -DQT_NO_CAST_FROM_ASCII )
add_definitions( -DQT_NO_CAST_TO_ASCII )
# allow to disable GHNS support on resource-constrained systems
option( ACCOUNTWIZARD_NO_GHNS "Disable GHNS support in the account wizard" ${KDEPIM_MOBILE_UI} )
if ( ACCOUNTWIZARD_NO_GHNS )
add_definitions( -DACCOUNTWIZARD_NO_GHNS )
endif ()
set(accountwizard_srcs
dialog.cpp
typepage.cpp
loadpage.cpp
global.cpp
page.cpp
dynamicpage.cpp
setupmanager.cpp
setuppage.cpp
resource.cpp
setupobject.cpp
transport.cpp
configfile.cpp
ldap.cpp
identity.cpp
servertest.cpp
personaldatapage.cpp
ispdb/ispdb.cpp
)
kde4_add_ui_files(accountwizard_srcs
ui/typepage.ui
ui/loadpage.ui
ui/setuppage.ui
ui/personaldatapage.ui
)
set(accountwizard_libs
${KDEPIMLIBS_AKONADI_LIBS}
${KDEPIMLIBS_MAILTRANSPORT_LIBS}
${KDEPIMLIBS_KPIMUTILS_LIBS}
${KDE4_KROSSCORE_LIBS}
${KDE4_KDECORE_LIBS}
${KDE4_KIO_LIBS}
${KDEPIMLIBS_KMIME_LIBS}
${KDEPIMLIBS_KPIMIDENTITIES_LIBS}
${QT_QTGUI_LIBRARY}
${QT_QTUITOOLS_LIBRARY}
)
if ( NOT ACCOUNTWIZARD_NO_GHNS )
set(accountwizard_srcs ${accountwizard_srcs} providerpage.cpp)
kde4_add_ui_files(accountwizard_srcs ui/providerpage.ui)
set(accountwizard_libs ${accountwizard_libs} ${KDE4_KNEWSTUFF3_LIBS})
endif ()
kde4_add_executable(accountwizard ${accountwizard_srcs} main.cpp)
target_link_libraries(accountwizard ${accountwizard_libs})
kde4_add_plugin(accountwizard_plugin ${accountwizard_srcs} inprocess-main.cpp)
target_link_libraries(accountwizard_plugin ${accountwizard_libs})
if ( NOT ACCOUNTWIZARD_NO_GHNS )
install(FILES accountwizard.knsrc DESTINATION ${CONFIG_INSTALL_DIR})
endif ()
install(TARGETS accountwizard ${INSTALL_TARGETS_DEFAULT_ARGS})
install(TARGETS accountwizard_plugin DESTINATION ${PLUGIN_INSTALL_DIR})
install(PROGRAMS accountwizard.desktop DESTINATION ${XDG_APPS_INSTALL_DIR})
install(FILES accountwizard-mime.xml DESTINATION ${XDG_MIME_INSTALL_DIR})
update_xdg_mimetypes(${XDG_MIME_INSTALL_DIR})
add_subdirectory(wizards)

View file

@ -0,0 +1,2 @@
You can create packages too... Want to read about it?
http://techbase.kde.org/Development/Tutorials/Akonadi/CreatingAccountWizardPackages

View file

@ -0,0 +1,3 @@
#!/bin/sh
$EXTRACTRC ui/*.ui >> rc.cpp
$XGETTEXT *.cpp ispdb/*.cpp -o $podir/accountwizard.pot

View file

@ -0,0 +1,5 @@
- figure out i18n for the actual wizards (DONE)
- imap+pop3wizard has no encryption as default i.c.w. plain auth method. Not a good default!
- remember which set up resources/transports/ldap accounts/identities belong together so we can offer to remove them in one go again
- add more wizards (In progress)
- sort out password fields at least for pop3.

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
<mime-type type="application/x-accountwizard-package">
<comment>KDE Accountwizard Package</comment>
<glob pattern="*.awp"></glob>
</mime-type>
</mime-info>

View file

@ -0,0 +1,97 @@
[Desktop Entry]
Name=Account Wizard
Name[bg]=Помощник за сметки
Name[bs]=Čarobnjak naloga
Name[ca]=Assistent de comptes
Name[ca@valencia]=Assistent de comptes
Name[cs]=Průvodce nastavením účtu
Name[da]=Kontoguide
Name[de]=Zugangsassistent
Name[el]=Οδηγός Λογαριασμού
Name[en_GB]=Account Wizard
Name[es]=Asistente de cuentas
Name[et]=Kontonõustaja
Name[fi]=Opastettu tilien asetus
Name[fr]=Assistant de comptes
Name[ga]=Treoraí Cuntais
Name[gl]=Asistente de contas
Name[hu]=Azonosítóbeállító varázsló
Name[ia]=Assistente de conto
Name[it]=Procedura guidata per la creazione di account
Name[ja]=
Name[kk]=Тіркелгі шебері
Name[km]=
Name[ko]=
Name[lt]=Paskyros vediklis
Name[lv]=Konta vednis
Name[mai]= ि
Name[nb]=Konto-veiviser
Name[nds]=Konto-Hölper
Name[nl]=Accountassistent
Name[pa]=
Name[pl]=Pomocnik konta
Name[pt]=Assistente de Contas
Name[pt_BR]=Assistente de contas
Name[ro]=Expert conturi
Name[ru]=Мастер учётных записей
Name[sk]=Sprievodca účtom
Name[sl]=Čarovnik za račune
Name[sr]=Чаробњак за налоге
Name[sr@ijekavian]=Чаробњак за налоге
Name[sr@ijekavianlatin]=Čarobnjak za naloge
Name[sr@latin]=Čarobnjak za naloge
Name[sv]=Kontoguide
Name[tr]=Hesap Sihirbazı
Name[ug]=زىيارەت يېتەكچىسى
Name[uk]=Майстер облікових записів
Name[x-test]=xxAccount Wizardxx
Name[zh_CN]=
Name[zh_TW]=
Exec=accountwizard --package %u
Type=Application
NoDisplay=true
Comment=Launch the account wizard to configure PIM accounts.
Comment[bs]=Pokreni čarobnjaka za naloge za konfigurisanje PIM naloga.
Comment[ca]=Llança l'assistent de comptes per a configurar comptes de PIM.
Comment[ca@valencia]=Llança l'assistent de comptes per a configurar comptes de PIM.
Comment[cs]=Spustit průvodce nastavením PIM účtů.
Comment[da]=Start kontoguiden for at konfigurere PIM-konti.
Comment[de]=Den Zugangsassistenten zum Einrichten von PIM-Zugängen starten.
Comment[el]=Εκτέλεση του οδηγού λογαριασμού για τη διαμόρφωση λογαριασμών PIM.
Comment[en_GB]=Launch the account wizard to configure PIM accounts.
Comment[es]=Lanzar el asistente de cuentas para configurar las cuentas PIM.
Comment[et]=Kontonõustaja käivitamine PIM-kontode seadistamiseks.
Comment[fi]=Käynnistä PIM-tilien opastettu asetus.
Comment[fr]=Lance l'assistant de compte pour configurer les comptes PIM.
Comment[gl]=Iniciar o asistente de contas para configurar as contas de información persoal
Comment[hu]=A PIM azonosítókat beállító varázsló elindítása.
Comment[ia]=Aperi le assistente de conto pro configurar contos del Administration de Informationes Personal
Comment[it]=Esegue la procedura guidata per la creazione di account per configurare gli account di PIM.
Comment[kk]=PIM тіркелгілерін баптау үшін шеберін жегеді.
Comment[km]= PIM 
Comment[ko]= PIM .
Comment[lt]=PIM paskyros nustatymui, paleisti paskyros vediklį.
Comment[lv]=Palaiž konta vedni, lai konfigurētu PIM kontus.
Comment[nb]=Start kontoveiviseren for å sette opp PIM-kontoer.
Comment[nds]=Konto-Hölper för't Inrichten vun PIM-Kontos starten
Comment[nl]=Start de accountassistent om PIM-accounts in te stellen.
Comment[pl]=Uruchom pomocnika konta, aby ustawić konta ZIO.
Comment[pt]=Lançar o assistente de contas para configurar as contas PIM.
Comment[pt_BR]=Executa o assistente para configuração das contas PIM.
Comment[ro]=Lansează expertul de conturi pentru a configura conturi noi.
Comment[ru]=Мастер для настройки учётных записей персонального информационного менеджера.
Comment[sk]=Spustí sprievodcu účtami na nasatavenie PIM účtov.
Comment[sl]=Zaženite čarovnika za nastavljanje računov za osebne podatke.
Comment[sr]=Покрените чаробњак да подесите ПИМ налоге.
Comment[sr@ijekavian]=Покрените чаробњак да подесите ПИМ налоге.
Comment[sr@ijekavianlatin]=Pokrenite čarobnjak da podesite PIM naloge.
Comment[sr@latin]=Pokrenite čarobnjak da podesite PIM naloge.
Comment[sv]=Starta kontoguiden för att anpassa konton för personlig informationshantering.
Comment[tr]=PIM hesaplarını düzenlemek için hesap sihirbazını başlat.
Comment[ug]=PIM ھېساباتلىرىنى سەپلەشتە ئىشلىتىدىغان ھېسابات يېتەكچىسىنى ئىجرا قىلىش
Comment[uk]=Запустити майстер облікових записів для налаштування.
Comment[x-test]=xxLaunch the account wizard to configure PIM accounts.xx
Comment[zh_CN]=
Comment[zh_TW]= PIM
MimeType=application/x-accountwizard-package;
Terminal=false

View file

@ -0,0 +1,5 @@
[KNewStuff3]
ProvidersUrl=http://download.kde.org/ocs/providers.xml
Categories=Akonadi Email Providers
TargetDir=akonadi/accountwizard
Uncompress=archive

View file

@ -0,0 +1,91 @@
/*
Copyright (c) 2010 Laurent Montel <montel@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 "configfile.h"
#include <KConfig>
#include <KConfigGroup>
#include <KLocalizedString>
#include <KStringHandler>
ConfigFile::ConfigFile( const QString & configName, QObject *parent )
: SetupObject( parent )
{
m_name = configName;
m_config = new KConfig( configName );
}
ConfigFile::~ConfigFile()
{
delete m_config;
}
void ConfigFile::write()
{
create();
}
void ConfigFile::create()
{
emit info( i18n( "Writing config file for %1...",m_name ) );
foreach ( const Config &c, m_configData ) {
KConfigGroup grp = m_config->group( c.group );
if ( c.obscure )
grp.writeEntry( c.key, KStringHandler::obscure( c.value ) );
else
grp.writeEntry( c.key, c.value );
}
m_config->sync();
emit finished( i18n( "Config file for %1 is writing.", m_name ) );
}
void ConfigFile::destroy()
{
emit info( i18n( "Config file for %1 was not changed.", m_name ) );
}
void ConfigFile::setName( const QString &name )
{
m_name = name;
}
void ConfigFile::setConfig( const QString &group, const QString &key, const QString &value )
{
Config conf;
conf.group = group;
conf.key = key;
conf.value = value;
conf.obscure = false;
m_configData.append( conf );
}
void ConfigFile::setPassword(const QString& group, const QString& key, const QString& value)
{
Config conf;
conf.group = group;
conf.key = key;
conf.value = value;
conf.obscure = true;
m_configData.append( conf );
}

View file

@ -0,0 +1,53 @@
/*
Copyright (c) 2010 Laurent Montel <montel@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 CONFIGFILE_H
#define CONFIGFILE_H
#include "setupobject.h"
class KConfig;
struct Config {
QString group;
QString key;
QString value;
bool obscure;
};
class ConfigFile : public SetupObject
{
Q_OBJECT
public:
explicit ConfigFile( const QString& configName, QObject *parent = 0 );
~ConfigFile();
void create();
void destroy();
public slots:
Q_SCRIPTABLE void write();
Q_SCRIPTABLE void setName( const QString & name );
Q_SCRIPTABLE void setConfig( const QString &group, const QString &key, const QString &value );
Q_SCRIPTABLE void setPassword( const QString &group, const QString &key, const QString &value );
private:
QList<Config> m_configData;
QString m_name;
KConfig *m_config;
};
#endif

View file

@ -0,0 +1,206 @@
/*
Copyright (c) 2009 Volker Krause <vkrause@kde.org>
Copyright (c) 2010 Tom Albers <toma@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 "dialog.h"
#include "personaldatapage.h"
#ifndef ACCOUNTWIZARD_NO_GHNS
#include "providerpage.h"
#endif
#include "typepage.h"
#include "loadpage.h"
#include "global.h"
#include "dynamicpage.h"
#include "setupmanager.h"
#include "servertest.h"
#include "setuppage.h"
#include <KMime/Message>
#include <klocalizedstring.h>
#include <kross/core/action.h>
#include <kdebug.h>
#include <kmessagebox.h>
#include <qplatformdefs.h>
Dialog::Dialog(QWidget* parent, Qt::WindowFlags flags ) :
KAssistantDialog( parent, flags )
{
#if defined (Q_WS_MAEMO_5) || defined (MEEGO_EDITION_HARMATTAN)
setWindowState( Qt::WindowFullScreen );
#endif
showButton( Help, false ); // we don't have help for the account wizard atm
mSetupManager = new SetupManager( this );
const bool showPersonalDataPage = Global::typeFilter().size() == 1 && Global::typeFilter().first() == KMime::Message::mimeType();
if ( showPersonalDataPage ) {
// todo: dont ask these details based on a setting of the desktop file.
PersonalDataPage *pdpage = new PersonalDataPage( this );
addPage( pdpage, i18n( "Provide personal data" ) );
connect( pdpage, SIGNAL(manualWanted(bool)), SLOT(slotManualConfigWanted(bool)) );
if ( !Global::assistant().isEmpty() ) {
pdpage->setHideOptionInternetSearch( true );
}
}
if ( Global::assistant().isEmpty() ) {
TypePage* typePage = new TypePage( this );
connect( typePage->treeview(), SIGNAL(doubleClicked(QModelIndex)), SLOT(slotNextPage()) );
#ifndef ACCOUNTWIZARD_NO_GHNS
connect( typePage, SIGNAL(ghnsWanted()), SLOT(slotGhnsWanted()) );
#endif
mTypePage = addPage( typePage, i18n( "Select Account Type" ) );
setAppropriate( mTypePage, false );
#ifndef ACCOUNTWIZARD_NO_GHNS
ProviderPage *ppage = new ProviderPage( this );
connect( typePage, SIGNAL(ghnsWanted()), ppage, SLOT(startFetchingData()) );
connect( ppage->treeview(), SIGNAL(doubleClicked(QModelIndex)), SLOT(slotNextPage()) );
connect( ppage, SIGNAL(ghnsNotWanted()), SLOT(slotGhnsNotWanted()) );
mProviderPage = addPage( ppage, i18n( "Select Provider" ) );
setAppropriate( mProviderPage, false );
#endif
}
LoadPage *loadPage = new LoadPage( this );
mLoadPage = addPage( loadPage, i18n( "Loading Assistant" ) );
setAppropriate( mLoadPage, false );
loadPage->exportObject( this, QLatin1String( "Dialog" ) );
loadPage->exportObject( mSetupManager, QLatin1String( "SetupManager" ) );
loadPage->exportObject( new ServerTest( this ), QLatin1String( "ServerTest" ) );
connect( loadPage, SIGNAL(aboutToStart()), SLOT(clearDynamicPages()) );
SetupPage *setupPage = new SetupPage( this );
mLastPage = addPage( setupPage, i18n( "Setting up Account" ) );
mSetupManager->setSetupPage( setupPage );
slotManualConfigWanted( !showPersonalDataPage );
Page *page = qobject_cast<Page*>( currentPage()->widget() );
page->enterPageNext();
emit page->pageEnteredNext();
enableButton( KDialog::Help, false );
}
KPageWidgetItem* Dialog::addPage(Page* page, const QString &title)
{
KPageWidgetItem *item = KAssistantDialog::addPage( page, title );
connect( page, SIGNAL(leavePageNextOk()), SLOT(slotNextOk()) );
connect( page, SIGNAL(leavePageBackOk()), SLOT(slotBackOk()) );
page->setPageWidgetItem( item );
return item;
}
void Dialog::slotNextPage()
{
next();
}
void Dialog::next()
{
Page *page = qobject_cast<Page*>( currentPage()->widget() );
page->leavePageNext();
page->leavePageNextRequested();
}
void Dialog::slotNextOk()
{
Page *page = qobject_cast<Page*>( currentPage()->widget() );
emit page->pageLeftNext();
KAssistantDialog::next();
page = qobject_cast<Page*>( currentPage()->widget() );
page->enterPageNext();
emit page->pageEnteredNext();
}
void Dialog::back()
{
Page *page = qobject_cast<Page*>( currentPage()->widget() );
page->leavePageBack();
page->leavePageBackRequested();
}
void Dialog::slotBackOk()
{
Page *page = qobject_cast<Page*>( currentPage()->widget() );
emit page->pageLeftBack();
KAssistantDialog::back();
page = qobject_cast<Page*>( currentPage()->widget() );
page->enterPageBack();
emit page->pageEnteredBack();
}
QObject* Dialog::addPage(const QString& uiFile, const QString &title )
{
kDebug() << uiFile;
DynamicPage *page = new DynamicPage( Global::assistantBasePath() + uiFile, this );
connect( page, SIGNAL(leavePageNextOk()), SLOT(slotNextOk()) );
connect( page, SIGNAL(leavePageBackOk()), SLOT(slotBackOk()) );
KPageWidgetItem* item = insertPage( mLastPage, page, title );
page->setPageWidgetItem( item );
mDynamicPages.push_back( item );
return page;
}
void Dialog::slotManualConfigWanted( bool show )
{
Q_ASSERT( mTypePage );
setAppropriate( mTypePage, show );
setAppropriate( mLoadPage, show );
}
#ifndef ACCOUNTWIZARD_NO_GHNS
void Dialog::slotGhnsWanted()
{
Q_ASSERT( mProviderPage );
setAppropriate( mProviderPage, true );
setCurrentPage( mProviderPage );
}
void Dialog::slotGhnsNotWanted()
{
Q_ASSERT( mProviderPage );
setAppropriate( mProviderPage, false );
}
#endif
SetupManager* Dialog::setupManager()
{
return mSetupManager;
}
void Dialog::clearDynamicPages()
{
foreach ( KPageWidgetItem *item, mDynamicPages )
removePage( item );
mDynamicPages.clear();
}
void Dialog::reject()
{
connect( mSetupManager, SIGNAL(rollbackComplete()), SLOT(close()) );
mSetupManager->requestRollback();
}

View file

@ -0,0 +1,69 @@
/*
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 DIALOG_H
#define DIALOG_H
#include "setupmanager.h"
#include <kassistantdialog.h>
class Page;
class TypePage;
class Dialog : public KAssistantDialog
{
Q_OBJECT
public:
explicit Dialog( QWidget *parent = 0, Qt::WindowFlags flags = 0 );
/* reimpl */ void next();
/* reimpl */ void back();
// give room for certain pages to create objects too.
SetupManager* setupManager();
public slots:
Q_SCRIPTABLE QObject* addPage( const QString &uiFile, const QString &title );
void reject();
private slots:
void slotNextPage();
#ifndef ACCOUNTWIZARD_NO_GHNS
void slotGhnsWanted();
void slotGhnsNotWanted();
#endif
void slotManualConfigWanted( bool );
void slotNextOk();
void slotBackOk();
void clearDynamicPages();
private:
KPageWidgetItem* addPage( Page* page, const QString &title );
private:
SetupManager* mSetupManager;
KPageWidgetItem* mLastPage;
KPageWidgetItem* mProviderPage;
KPageWidgetItem* mTypePage;
KPageWidgetItem* mLoadPage;
QVector<KPageWidgetItem*> mDynamicPages;
};
#endif

View file

@ -0,0 +1,65 @@
/*
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.
*/
#include "dynamicpage.h"
#include <KDebug>
#include <QUiLoader>
#include <QFile>
#include <qboxlayout.h>
#include <qscrollarea.h>
DynamicPage::DynamicPage(const QString& uiFile, KAssistantDialog* parent) : Page( parent )
{
QVBoxLayout *layout = new QVBoxLayout;
layout->setMargin( 0 );
setLayout( layout );
#ifdef KDEPIM_MOBILE_UI
// for mobile ui we put the page into a scroll area in case it's too big
QScrollArea *pageParent = new QScrollArea( this );
pageParent->setFrameShape( QFrame::NoFrame );
pageParent->setWidgetResizable( true );
layout->addWidget( pageParent );
#else
QWidget *pageParent = this;
#endif
QUiLoader loader;
QFile file( uiFile );
file.open( QFile::ReadOnly );
kDebug() << uiFile;
m_dynamicWidget = loader.load( &file, pageParent );
file.close();
#ifdef KDEPIM_MOBILE_UI
pageParent->setWidget( m_dynamicWidget );
#else
layout->addWidget( m_dynamicWidget );
#endif
setValid( true );
}
QObject* DynamicPage::widget() const
{
return m_dynamicWidget;
}

View file

@ -0,0 +1,39 @@
/*
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 DYNAMICPAGE_H
#define DYNAMICPAGE_H
#include "page.h"
class DynamicPage : public Page
{
Q_OBJECT
public:
explicit DynamicPage( const QString &uiFile, KAssistantDialog* parent = 0 );
public slots:
/// returns the top-level widget of the UI file
Q_SCRIPTABLE QObject* widget() const;
private:
QWidget* m_dynamicWidget;
};
#endif

View file

@ -0,0 +1,115 @@
/*
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.
*/
#include "global.h"
#include <kdebug.h>
#include <KGlobal>
#include <KStandardDirs>
#include <QtCore/qfileinfo.h>
#include <QtCore/QDir>
#include <kio/copyjob.h>
#include <kio/netaccess.h>
class GlobalPrivate
{
public:
QStringList filter;
QString assistant;
};
K_GLOBAL_STATIC( GlobalPrivate, sInstance )
QString Global::assistant()
{
return sInstance->assistant;
}
void Global::setAssistant(const QString& assistant)
{
const QFileInfo info( assistant );
if ( info.isAbsolute() ) {
sInstance->assistant = assistant;
return;
}
const QStringList list = KGlobal::dirs()->findAllResources(
"data", QLatin1String( "akonadi/accountwizard/*.desktop" ),
KStandardDirs::Recursive | KStandardDirs::NoDuplicates );
foreach ( const QString &entry, list ) {
const QFileInfo info( entry );
const QDir dir( info.absolutePath() );
kDebug() << dir.dirName();
if ( dir.dirName() == assistant ) {
sInstance->assistant = entry;
return;
}
}
sInstance->assistant.clear();
}
QStringList Global::typeFilter()
{
return sInstance->filter;
}
void Global::setTypeFilter(const QStringList& filter)
{
sInstance->filter = filter;
}
QString Global::assistantBasePath()
{
const QFileInfo info( assistant() );
if ( info.isAbsolute() )
return info.absolutePath() + QDir::separator();
return QString();
}
QString Global::unpackAssistant( const KUrl& remotePackageUrl )
{
QString localPackageFile;
if ( remotePackageUrl.protocol() == QLatin1String( "file" ) ) {
localPackageFile = remotePackageUrl.path();
} else {
QString remoteFileName = QFileInfo( remotePackageUrl.path() ).fileName();
localPackageFile = KStandardDirs::locateLocal( "cache", QLatin1String("accountwizard/") + remoteFileName );
KIO::Job* job = KIO::copy( remotePackageUrl, localPackageFile, KIO::Overwrite | KIO::HideProgressInfo );
kDebug() << "downloading remote URL" << remotePackageUrl << "to" << localPackageFile;
if ( !KIO::NetAccess::synchronousRun( job, 0 ) )
return QString();
}
const KUrl file( QLatin1String("tar://") + localPackageFile );
const QFileInfo fi( localPackageFile );
const QString assistant = fi.baseName();
const QString dest = KStandardDirs::locateLocal( "appdata", QLatin1String("/") );
KStandardDirs::makeDir( dest + file.fileName() );
KIO::Job* getJob = KIO::copy( file, dest, KIO::Overwrite | KIO::HideProgressInfo );
if ( KIO::NetAccess::synchronousRun( getJob, 0 ) ) {
kDebug() << "worked, unpacked in " << dest;
return dest + file.fileName() + QLatin1Char('/') + assistant + QLatin1Char('/') + assistant + QLatin1String(".desktop");
} else {
kDebug() << "failed" << getJob->errorString();
return QString();
}
}

View file

@ -0,0 +1,39 @@
/*
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 GLOBAL_H
#define GLOBAL_H
#include <KUrl>
#include <QStringList>
namespace Global
{
QStringList typeFilter();
void setTypeFilter( const QStringList &filter );
QString assistant();
void setAssistant( const QString &assistant );
QString assistantBasePath();
QString unpackAssistant( const KUrl& remotePackageUrl );
}
#endif

View file

@ -0,0 +1,152 @@
/*
Copyright (c) 2010 Laurent Montel <montel@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 "identity.h"
#include "transport.h"
#include <kpimidentities/identitymanager.h>
#include <kpimidentities/identity.h>
#include <KLocalizedString>
Identity::Identity( QObject *parent )
: SetupObject( parent ),
m_transport( 0 )
{
m_manager = new KPIMIdentities::IdentityManager( false, this, "mIdentityManager" );
m_identity = &m_manager->newFromScratch( QString() );
Q_ASSERT( m_identity != 0 );
}
Identity::~Identity()
{
delete m_manager;
}
void Identity::create()
{
emit info( i18n( "Setting up identity..." ) );
// store identity information
// TODO now that we have the identity object around anyway we can probably get rid of most of the other members
m_identity->setIdentityName( identityName() );
m_identity->setFullName( m_realName );
m_identity->setPrimaryEmailAddress( m_email );
m_identity->setOrganization( m_organization );
if ( m_transport && m_transport->transportId() > 0 )
m_identity->setTransport( QString::number( m_transport->transportId() ) );
if ( !m_signature.isEmpty() ) {
const KPIMIdentities::Signature sig( m_signature );
m_identity->setSignature( sig );
}
if ( !m_prefCryptoFormat.isEmpty() )
m_identity->setPreferredCryptoMessageFormat( m_prefCryptoFormat );
if ( !m_xface.isEmpty() ) {
m_identity->setXFaceEnabled( true );
m_identity->setXFace( m_xface );
}
m_manager->setAsDefault( m_identity->uoid() );
m_manager->commit();
emit finished( i18n( "Identity set up." ) );
}
QString Identity::identityName() const
{
// create identity name
QString name( m_identityName );
if ( name.isEmpty() ) {
name = i18nc( "Default name for new email accounts/identities.", "Unnamed" );
QString idName = m_email;
int pos = idName.indexOf( QLatin1Char('@') );
if ( pos != -1 ) {
name = idName.mid( 0, pos );
}
// Make the name a bit more human friendly
name.replace( QLatin1Char('.'), QLatin1Char(' ') );
pos = name.indexOf( QLatin1Char(' ') );
if ( pos != 0 ) {
name[ pos + 1 ] = name[ pos + 1 ].toUpper();
}
name[ 0 ] = name[ 0 ].toUpper();
}
if ( !m_manager->isUnique( name ) ) {
name = m_manager->makeUnique( name );
}
return name;
}
void Identity::destroy()
{
m_manager->removeIdentityForced( m_identity->identityName() );
m_manager->commit();
m_identity = 0;
emit info( i18n( "Identity removed." ) );
}
void Identity::setIdentityName(const QString& name)
{
m_identityName = name;
}
void Identity::setRealName( const QString &name )
{
m_realName = name;
}
void Identity::setOrganization( const QString &org )
{
m_organization = org;
}
void Identity::setEmail( const QString &email )
{
m_email = email;
}
uint Identity::uoid() const
{
return m_identity->uoid();
}
void Identity::setTransport(QObject* transport)
{
m_transport = qobject_cast<Transport*>( transport );
setDependsOn( qobject_cast<SetupObject*>( transport ) );
}
void Identity::setSignature(const QString& sig)
{
m_signature = sig;
}
void Identity::setPreferredCryptoMessageFormat(const QString& format)
{
m_prefCryptoFormat = format;
}
void Identity::setXFace(const QString& xface)
{
m_xface = xface;
}

View file

@ -0,0 +1,68 @@
/*
Copyright (c) 2010 Laurent Montel <montel@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 IDENTITY_H
#define IDENTITY_H
#include "setupobject.h"
class Transport;
namespace KPIMIdentities {
class Identity;
class IdentityManager;
}
class Identity : public SetupObject
{
Q_OBJECT
public:
explicit Identity( QObject *parent = 0 );
~Identity();
void create();
void destroy();
public slots:
Q_SCRIPTABLE void setIdentityName( const QString &name );
Q_SCRIPTABLE void setRealName( const QString & name );
Q_SCRIPTABLE void setEmail( const QString &email );
Q_SCRIPTABLE void setOrganization( const QString &org );
Q_SCRIPTABLE void setSignature( const QString &sig );
Q_SCRIPTABLE uint uoid() const;
Q_SCRIPTABLE void setTransport( QObject* transport );
Q_SCRIPTABLE void setPreferredCryptoMessageFormat( const QString &format );
Q_SCRIPTABLE void setXFace( const QString &xface );
protected:
QString identityName() const;
private:
QString m_identityName;
QString m_realName;
QString m_email;
QString m_organization;
QString m_signature;
QString m_prefCryptoFormat;
QString m_xface;
Transport *m_transport;
KPIMIdentities::IdentityManager *m_manager;
KPIMIdentities::Identity *m_identity;
};
#endif

View file

@ -0,0 +1,46 @@
/*
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 "dialog.h"
#include "global.h"
#include <kglobal.h>
#include <QtCore/QObject>
#include <QtCore/QtPlugin>
#include <QtCore/QStringList>
class AccountWizard : public QObject
{
Q_OBJECT
public:
explicit AccountWizard( QObject* parent = 0 ) : QObject( parent ) {}
public slots:
void run( const QStringList &types, QWidget *parent )
{
if ( !types.isEmpty() )
Global::setTypeFilter( types );
Dialog dlg( parent );
dlg.exec();
}
};
Q_EXPORT_PLUGIN2( accountwizard, AccountWizard )
#include "inprocess-main.moc"

View file

@ -0,0 +1,15 @@
set(ispdb_srcs
main.cpp
ispdb.cpp
)
kde4_add_executable(ispdb ${ispdb_srcs})
target_link_libraries(ispdb
${KDE4_KDECORE_LIBS}
${KDE4_KIO_LIBS}
${KDEPIMLIBS_KMIME_LIBS}
)
install(TARGETS ispdb ${INSTALL_TARGETS_DEFAULT_ARGS})

View file

@ -0,0 +1,277 @@
/*
Copyright (c) 2010 Omat Holding B.V. <info@omat.nl>
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 "ispdb.h"
#include <kdebug.h>
#include <kio/job.h>
#include <kio/jobclasses.h>
#include <KLocalizedString>
#include <kmime/kmime_header_parsing.h>
#include <QDomDocument>
Ispdb::Ispdb( QObject *parent )
: QObject( parent ), mServerType( DataBase )
{
}
Ispdb::~Ispdb()
{
}
void Ispdb::setEmail( const QString& address )
{
KMime::Types::Mailbox box;
box.fromUnicodeString( address );
mAddr = box.addrSpec();
}
void Ispdb::start()
{
kDebug() << mAddr.asString();
// we should do different things in here. But lets focus in the db first.
lookupInDb();
}
void Ispdb::startJob( const KUrl&url )
{
QMap< QString, QVariant > map;
map[QLatin1String("errorPage")] = false;
KIO::TransferJob* job = KIO::get( url, KIO::NoReload, KIO::HideProgressInfo );
job->setMetaData( map );
connect( job, SIGNAL(result(KJob*)),
this, SLOT(slotResult(KJob*)) );
connect( job, SIGNAL(data(KIO::Job*,QByteArray)),
this, SLOT(dataArrived(KIO::Job*,QByteArray)) );
}
void Ispdb::lookupInDb()
{
KUrl url;
switch( mServerType )
{
case IspAutoConfig:
{
url = KUrl( QLatin1String("http://autoconfig.") + mAddr.domain.toLower() + QLatin1String("/mail/config-v1.1.xml?emailaddress=") + mAddr.asString().toLower() );
Q_EMIT searchType(i18n("Lookup configuration: Email provider"));
break;
}
case IspWellKnow:
{
url = KUrl( QLatin1String("http://") + mAddr.domain.toLower() + QLatin1String("/.well-known/autoconfig/mail/config-v1.1.xml") );
Q_EMIT searchType(i18n("Lookup configuration: Trying common server name"));
break;
}
case DataBase:
{
url = KUrl( QLatin1String("https://autoconfig.thunderbird.net/v1.1/") + mAddr.domain.toLower() );
Q_EMIT searchType(i18n("Lookup configuration: Mozilla database"));
break;
}
}
startJob( url );
}
void Ispdb::slotResult( KJob* job )
{
if ( job->error() ) {
kDebug() << "Fetching failed" << job->errorString();
bool lookupFinished = false;
switch( mServerType ) {
case IspAutoConfig: {
mServerType = IspWellKnow;
break;
}
case IspWellKnow: {
lookupFinished = true;
break;
}
case DataBase: {
mServerType = IspAutoConfig;
break;
}
}
if ( lookupFinished )
{
emit finished( false );
return;
}
lookupInDb();
return;
}
//kDebug() << mData;
QDomDocument document;
bool ok = document.setContent( mData );
if ( !ok ) {
kDebug() << "Could not parse xml" << mData;
emit finished( false );
return;
}
QDomElement docElem = document.documentElement();
QDomNode m = docElem.firstChild(); // emailprovider
QDomNode n = m.firstChild(); // emailprovider
while ( !n.isNull() ) {
QDomElement e = n.toElement();
if ( !e.isNull() ) {
//kDebug() << qPrintable( e.tagName() );
const QString tagName( e.tagName() );
if ( tagName == QLatin1String( "domain" ) )
mDomains << e.text();
else if ( tagName == QLatin1String( "displayName" ) )
mDisplayName = e.text();
else if ( tagName == QLatin1String( "displayShortName" ) )
mDisplayShortName = e.text();
else if ( tagName == QLatin1String( "incomingServer" )
&& e.attribute( QLatin1String("type") ) == QLatin1String( "imap" ) ) {
server s = createServer( e );
if (s.isValid())
mImapServers.append( s );
} else if ( tagName == QLatin1String( "incomingServer" )
&& e.attribute( QLatin1String("type") ) == QLatin1String( "pop3" ) ) {
server s = createServer( e );
if (s.isValid())
mPop3Servers.append( s );
} else if ( tagName == QLatin1String( "outgoingServer" )
&& e.attribute( QLatin1String("type") ) == QLatin1String( "smtp" ) ) {
server s = createServer( e );
if (s.isValid())
mSmtpServers.append( s );
}
}
n = n.nextSibling();
}
// comment this section out when you are tired of it...
kDebug() << "------------------ summary --------------";
kDebug() << "Domains" << mDomains;
kDebug() << "Name" << mDisplayName << "(" << mDisplayShortName << ")";
kDebug() << "Imap servers:";
foreach ( const server& s, mImapServers ) {
kDebug() << s.hostname << s.port << s.socketType << s.username << s.authentication;
}
kDebug() << "pop3 servers:";
foreach ( const server& s, mPop3Servers ) {
kDebug() << s.hostname << s.port << s.socketType << s.username << s.authentication;
}
kDebug() << "smtp servers:";
foreach ( const server& s, mSmtpServers ) {
kDebug() << s.hostname << s.port << s.socketType << s.username << s.authentication;
}
// end section.
emit finished( true );
}
server Ispdb::createServer( const QDomElement& n )
{
QDomNode o = n.firstChild();
server s;
while ( !o.isNull() ) {
QDomElement f = o.toElement();
if ( !f.isNull() ) {
const QString tagName( f.tagName() );
if ( tagName == QLatin1String( "hostname" ) )
s.hostname = replacePlaceholders( f.text() );
else if ( tagName == QLatin1String( "port" ) )
s.port = f.text().toInt();
else if ( tagName == QLatin1String( "socketType" ) ) {
const QString type( f.text() );
if ( type == QLatin1String( "plain" ) )
s.socketType = None;
else if ( type == QLatin1String( "SSL" ) )
s.socketType = SSL;
if ( type == QLatin1String( "STARTTLS" ) )
s.socketType = StartTLS;
} else if ( tagName == QLatin1String( "username" ) ) {
s.username = replacePlaceholders( f.text() );
} else if ( tagName == QLatin1String( "authentication" ) ) {
const QString type( f.text() );
if ( type == QLatin1String( "password-cleartext" )
|| type == QLatin1String( "plain" ) )
s.authentication = Plain;
else if ( type == QLatin1String( "password-encrypted" )
|| type == QLatin1String( "secure" ) )
s.authentication = CramMD5;
else if ( type == QLatin1String( "NTLM" ) )
s.authentication = NTLM;
else if ( type == QLatin1String( "GSSAPI" ) )
s.authentication = GSSAPI;
else if ( type == QLatin1String( "client-ip-based" ) )
s.authentication = ClientIP;
else if ( type == QLatin1String( "none" ) )
s.authentication = NoAuth;
}
}
o = o.nextSibling();
}
return s;
}
QString Ispdb::replacePlaceholders( const QString& in )
{
QString out( in );
out.replace( QLatin1String("%EMAILLOCALPART%"), mAddr.localPart );
out.replace( QLatin1String("%EMAILADDRESS%"), mAddr.asString() );
out.replace( QLatin1String("%EMAILDOMAIN%"), mAddr.domain );
return out;
}
void Ispdb::dataArrived( KIO::Job*, const QByteArray& data )
{
mData.append( data );
}
// The getters
QStringList Ispdb::relevantDomains() const
{
return mDomains;
}
QString Ispdb::name( length l ) const
{
if ( l == Long )
return mDisplayName;
else if ( l == Short )
return mDisplayShortName;
else
return QString(); //make compiler happy. Not me.
}
QList< server > Ispdb::imapServers() const
{
return mImapServers;
}
QList< server > Ispdb::pop3Servers() const
{
return mPop3Servers;
}
QList< server > Ispdb::smtpServers() const
{
return mSmtpServers;
}

View file

@ -0,0 +1,133 @@
/*
Copyright (c) 2010 Omat Holding B.V. <info@omat.nl>
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 ISPDB_H
#define ISPDB_H
#include <QObject>
#include <kio/job.h>
#include <kmime/kmime_header_parsing.h>
class QDomElement;
struct server;
/**
This class will search in Mozilla's database for an xml file
describing the isp data belonging to that address. This class
searches and wraps the result for further usage. References:
https://wiki.mozilla.org/Thunderbird:Autoconfiguration
https://developer.mozilla.org/en/Thunderbird/Autoconfiguration
https://ispdb.mozillamessaging.com/
*/
class Ispdb : public QObject
{
Q_OBJECT
public:
enum socketType { None = 0, SSL, StartTLS };
/**
Ispdb uses custom authtyps, hence the enum here.
@see https://wiki.mozilla.org/Thunderbird:Autoconfiguration:ConfigFileFormat
In particular, note that Ispdb's Plain represents both Cleartext and AUTH Plain
We will always treat it as Cleartext
*/
enum authType { Plain = 0, CramMD5, NTLM, GSSAPI, ClientIP, NoAuth };
enum length { Long = 0, Short };
/** Constructor */
explicit Ispdb( QObject *parent = 0 );
/** Destructor */
~Ispdb();
/** After finished() has been emitted you can
retrieve the domains that are covered by these
settings */
QStringList relevantDomains() const;
/** After finished() has been emitted you can
get the name of the provider, you can get a long
name and a short one */
QString name( length ) const;
/** After finished() has been emitted you can
get a list of imap servers available for this provider */
QList< server > imapServers() const;
/** After finished() has been emitted you can
get a list of pop3 servers available for this provider */
QList< server > pop3Servers() const;
/** After finished() has been emitted you can
get a list of smtp servers available for this provider */
QList< server > smtpServers() const;
public slots:
/** Sets the emailaddress you want to servers for */
void setEmail( const QString& );
/** Starts looking up the servers which belong to the e-mailaddress */
void start();
private slots:
void slotResult( KJob* );
void dataArrived( KIO::Job*, const QByteArray& data );
signals:
/** emitted when done. **/
void finished( bool );
void searchType( const QString &type );
private:
enum searchServerType { IspAutoConfig = 0, IspWellKnow, DataBase };
server createServer( const QDomElement& n );
void lookupInDb();
QString replacePlaceholders( const QString& );
void startJob( const KUrl&url );
KMime::Types::AddrSpec mAddr; // emailaddress
QByteArray mData; // storage of incoming data from kio
// storage of the results
QStringList mDomains;
QString mDisplayName, mDisplayShortName;
QList< server > mImapServers, mPop3Servers, mSmtpServers;
Ispdb::searchServerType mServerType;
};
struct server {
server() {
port = -1;
authentication = Ispdb::Plain;
socketType = Ispdb::None;
}
bool isValid() const {
return (port != -1);
}
QString hostname;
int port;
Ispdb::socketType socketType;
QString username;
Ispdb::authType authentication;
};
#endif

View file

@ -0,0 +1,61 @@
/*
Copyright (c) 2010 Omat Holding B.V. <info@omat.nl>
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 "ispdb.h"
#include <kaboutdata.h>
#include <kapplication.h>
#include <kcmdlineargs.h>
#include <kglobal.h>
int main( int argc, char **argv )
{
KAboutData aboutData( "ispdb", 0,
ki18n( "ISPDB Assistant" ),
"0.1",
ki18n( "Helps setting up PIM accounts" ),
KAboutData::License_LGPL,
ki18n( "(c) 2010 Omat Holding B.V." ),
KLocalizedString(),
"http://pim.kde.org/akonadi/" );
aboutData.setProgramIconName( "akonadi" );
aboutData.addAuthor( ki18n( "Tom Albers" ), ki18n( "Author" ), "toma@kde.org" );
KCmdLineArgs::init( argc, argv, &aboutData );
KCmdLineOptions options;
options.add( "email <emailaddress>", ki18n( "Tries to fetch the settings for that email address" ) );
KCmdLineArgs::addCmdLineOptions( options );
KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
QString email;
if ( !args->getOption( "email" ).isEmpty() )
email = args->getOption( "email" );
else
email = "blablabla@gmail.com";
KApplication app;
Ispdb ispdb;
ispdb.setEmail( email );
ispdb.start();
return app.exec();
}

View file

@ -0,0 +1,117 @@
/*
Copyright (c) 2010 Laurent Montel <montel@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 "ldap.h"
#include <KConfig>
#include <KConfigGroup>
#include <KLocalizedString>
Ldap::Ldap( QObject *parent )
: SetupObject( parent )
{
}
Ldap::~Ldap()
{
}
void Ldap::create()
{
emit info( i18n( "Setting up LDAP server..." ) );
if ( m_server.isEmpty() || m_user.isEmpty() )
return;
const QString host = m_server;
// Figure out the basedn
QString basedn = host;
// If the user gave a full email address, the domain name
// of that overrides the server name for the ldap dn
const QString user = m_user;
int pos = user.indexOf( QLatin1String("@") );
if ( pos > 0 ) {
const QString h = user.mid( pos+1 );
if ( !h.isEmpty() )
// The user did type in a domain on the email address. Use that
basedn = h;
}
{ // while we're here, write default domain
KConfig c( QLatin1String("kmail2rc") );
KConfigGroup group = c.group( "General" );
group.writeEntry( "Default domain", basedn );
}
basedn.replace( QLatin1Char('.'), QLatin1String(",dc=") );
basedn.prepend( QLatin1String("dc=") );
// Set the changes
KConfig c( QLatin1String("kabldaprc") );
KConfigGroup group = c.group( "LDAP" );
bool hasMyServer = false;
uint selHosts = group.readEntry( "NumSelectedHosts", 0 );
for ( uint i = 0 ; i < selHosts && !hasMyServer; ++i )
if ( group.readEntry( QString::fromLatin1( "SelectedHost%1" ).arg( i ), QString() ) == host )
hasMyServer = true;
if ( !hasMyServer ) {
group.writeEntry( "NumSelectedHosts", selHosts + 1 );
group.writeEntry( QString::fromLatin1( "SelectedHost%1" ).arg( selHosts ), host );
group.writeEntry( QString::fromLatin1( "SelectedBase%1" ).arg( selHosts ), basedn );
group.writeEntry( QString::fromLatin1( "SelectedPort%1" ).arg( selHosts ), "389" );
if ( !m_authMethod.isEmpty() ) {
group.writeEntry( QString::fromLatin1( "SelectedAuth%1" ).arg( selHosts ), m_authMethod );
group.writeEntry( QString::fromLatin1( "SelectedBind%1" ).arg( selHosts ), m_bindDn );
group.writeEntry( QString::fromLatin1( "SelectedPwdBind%1" ).arg( selHosts ), m_password );
}
}
emit finished( i18n( "LDAP set up." ) );
}
void Ldap::destroy()
{
emit info( i18n( "LDAP not configuring." ) );
}
void Ldap::setUser( const QString &user )
{
m_user = user;
}
void Ldap::setServer( const QString &server )
{
m_server = server;
}
void Ldap::setAuthenticationMethod(const QString& meth)
{
m_authMethod = meth;
}
void Ldap::setBindDn(const QString& bindDn)
{
m_bindDn = bindDn;
}
void Ldap::setPassword(const QString& password)
{
m_password = password;
}

View file

@ -0,0 +1,48 @@
/*
Copyright (c) 2010 Laurent Montel <montel@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 LDAP_H
#define LDAP_H
#include "setupobject.h"
class Ldap : public SetupObject
{
Q_OBJECT
public:
explicit Ldap( QObject *parent = 0 );
~Ldap();
void create();
void destroy();
public slots:
Q_SCRIPTABLE void setUser( const QString & name );
Q_SCRIPTABLE void setServer( const QString &server );
Q_SCRIPTABLE void setAuthenticationMethod( const QString &meth );
Q_SCRIPTABLE void setBindDn( const QString &bindDn );
Q_SCRIPTABLE void setPassword( const QString &password );
private:
QString m_user;
QString m_server;
QString m_bindDn;
QString m_authMethod;
QString m_password;
};
#endif

View file

@ -0,0 +1,88 @@
/*
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.
*/
#include "loadpage.h"
#include "global.h"
#include <kassistantdialog.h>
#include <kconfig.h>
#include <kconfiggroup.h>
#include <kross/core/action.h>
#include <QtCore/qfile.h>
LoadPage::LoadPage(KAssistantDialog* parent) :
Page( parent ),
m_action( 0 )
{
ui.setupUi( this );
setValid( false );
}
void LoadPage::enterPageNext()
{
setValid( false );
// FIXME: deletion seems to delete the exported objects as well, killing the entire wizard...
//delete m_action;
m_action = 0;
emit aboutToStart();
const KConfig f( Global::assistant() );
KConfigGroup grp( &f, "Wizard" );
const QString scriptFile = grp.readEntry( "Script", QString() );
if ( scriptFile.isEmpty() ) {
ui.statusLabel->setText( i18n( "No script specified in '%1'.", Global::assistant() ) );
return;
}
if ( !QFile::exists( Global::assistantBasePath() + scriptFile ) ) {
ui.statusLabel->setText( i18n( "Unable to load assistant: File '%1' does not exist.", Global::assistantBasePath() + scriptFile ) );
return;
}
ui.statusLabel->setText( i18n( "Loading script '%1'...", Global::assistantBasePath() + scriptFile ) );
m_action = new Kross::Action( this, QLatin1String("AccountWizard") );
typedef QPair<QObject*, QString> ObjectStringPair;
foreach ( const ObjectStringPair &exportedObject, m_exportedObjects )
m_action->addQObject( exportedObject.first, exportedObject.second );
if ( !m_action->setFile( Global::assistantBasePath() + scriptFile ) ) {
ui.statusLabel->setText( i18n( "Failed to load script: '%1'.", m_action->errorMessage() ) );
return;
}
KConfigGroup grpTranslate( &f, "Translate" );
const QString poFileName = grpTranslate.readEntry( "Filename" );
if ( !poFileName.isEmpty() )
KGlobal::locale()->insertCatalog( poFileName );
m_action->trigger();
m_parent->next();
}
void LoadPage::enterPageBack()
{
// TODO: if we are the first page, call enterPageNext(), hm, can we get here then at all?
m_parent->back();
}
void LoadPage::exportObject(QObject* object, const QString& name)
{
m_exportedObjects.push_back( qMakePair( object, name ) );
}

View file

@ -0,0 +1,51 @@
/*
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 LOADPAGE_H
#define LOADPAGE_H
#include "page.h"
#include "ui_loadpage.h"
namespace Kross {
class Action;
}
class LoadPage : public Page
{
Q_OBJECT
public:
explicit LoadPage( KAssistantDialog *parent );
virtual void enterPageNext();
virtual void enterPageBack();
void exportObject( QObject *object, const QString &name );
Q_SIGNALS:
void aboutToStart();
private:
Ui::LoadPage ui;
QVector< QPair< QObject*, QString > > m_exportedObjects;
Kross::Action* m_action;
};
#endif

View file

@ -0,0 +1,81 @@
/*
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.
*/
#include "dialog.h"
#include "global.h"
#include <akonadi/control.h>
#include <kaboutdata.h>
#include <kapplication.h>
#include <kcmdlineargs.h>
#include <kglobal.h>
#include <KUniqueApplication>
#include <stdio.h>
int main( int argc, char **argv )
{
KAboutData aboutData( "accountwizard", 0,
ki18n( "Account Assistant" ),
"0.1",
ki18n( "Helps setting up PIM accounts" ),
KAboutData::License_LGPL,
ki18n( "(c) 2009 the Akonadi developers" ),
KLocalizedString(),
"http://pim.kde.org/akonadi/" );
aboutData.setProgramIconName( QLatin1String("akonadi") );
aboutData.addAuthor( ki18n( "Volker Krause" ), ki18n( "Author" ), "vkrause@kde.org" );
aboutData.addAuthor( ki18n( "Laurent Montel" ), KLocalizedString() , "montel@kde.org" );
KCmdLineArgs::init( argc, argv, &aboutData );
KCmdLineOptions options;
options.add( "type <type>", ki18n( "Only offer accounts that support the given type." ) );
options.add( "assistant <assistant>", ki18n( "Run the specified assistant." ) );
options.add( "package <fullpath>", ki18n( "unpack fullpath on startup and launch that assistant" ) );
KCmdLineArgs::addCmdLineOptions( options );
KUniqueApplication::addCmdLineOptions();
if ( !KUniqueApplication::start() ) {
fprintf( stderr, "accountwizard is already running!\n" );
exit( 0 );
}
KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
KUniqueApplication app;
KGlobal::locale()->insertCatalog( QLatin1String("libakonadi") );
Akonadi::Control::start( 0 );
if ( !args->getOption( "package" ).isEmpty() ) {
Global::setAssistant( Global::unpackAssistant( KUrl( args->getOption( "package" ) ) ) );
} else
Global::setAssistant( args->getOption( "assistant" ) );
if ( !args->getOption( "type" ).isEmpty() )
Global::setTypeFilter( args->getOption( "type" ).split( QLatin1Char(',') ) );
args->clear();
Dialog dlg( 0/*, Qt::WindowStaysOnTopHint*/ );
dlg.show();
return app.exec();
}

View file

@ -0,0 +1,60 @@
/*
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.
*/
#include "page.h"
#include <kpagewidgetmodel.h>
#include <kassistantdialog.h>
Page::Page(KAssistantDialog* parent):
QWidget(parent),
m_item( 0 ),
m_parent( parent ),
m_valid( false )
{
}
void Page::setPageWidgetItem(KPageWidgetItem* item)
{
m_item = item;
m_parent->setValid( m_item, m_valid );
}
void Page::setValid(bool valid)
{
if ( !m_item )
m_valid = valid;
else
m_parent->setValid( m_item, valid );
}
void Page::nextPage()
{
m_parent->next();
}
void Page::enterPageBack() {}
void Page::enterPageNext() {}
void Page::leavePageBack() {}
void Page::leavePageNext() {}
void Page::leavePageBackRequested() { emit leavePageBackOk(); }
void Page::leavePageNextRequested() { emit leavePageNextOk(); }

View file

@ -0,0 +1,64 @@
/*
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 PAGE_H
#define PAGE_H
#include <QtGui/QWidget>
class KAssistantDialog;
class KPageWidgetItem;
class Page : public QWidget
{
Q_OBJECT
public:
explicit Page( KAssistantDialog *parent );
void setPageWidgetItem( KPageWidgetItem *item );
virtual void enterPageNext();
virtual void enterPageBack();
virtual void leavePageNext();
virtual void leavePageBack();
virtual void leavePageNextRequested();
virtual void leavePageBackRequested();
signals:
Q_SCRIPTABLE void pageEnteredNext();
Q_SCRIPTABLE void pageEnteredBack();
Q_SCRIPTABLE void pageLeftNext();
Q_SCRIPTABLE void pageLeftBack();
Q_SCRIPTABLE void leavePageNextOk();
Q_SCRIPTABLE void leavePageBackOk();
public slots:
Q_SCRIPTABLE void setValid( bool valid );
Q_SCRIPTABLE void nextPage();
protected:
KPageWidgetItem *m_item;
KAssistantDialog *m_parent;
private:
friend class Dialog;
bool m_valid;
};
#endif // PAGE_H

View file

@ -0,0 +1,278 @@
/*
Copyright (c) 2009 Volker Krause <vkrause@kde.org>
Copyright (c) 2010 Tom Albers <toma@kde.org>
Copyright (c) 2012 Laurent Montel <montel@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 "personaldatapage.h"
#include "config-enterprise.h"
#include "global.h"
#include "dialog.h"
#include "transport.h"
#include "resource.h"
#include "ispdb/ispdb.h"
#include <kpimutils/emailvalidator.h>
#include <kpimutils/email.h>
#include <mailtransport/transport.h>
#include <KDebug>
QString accountName(Ispdb *ispdb, QString username)
{
const int pos(username.indexOf(QLatin1Char('@')));
username = username.left(pos);
return ispdb->name( Ispdb::Long ) + QString::fromLatin1(" (%1)").arg(username);
}
PersonalDataPage::PersonalDataPage(Dialog* parent) :
Page( parent ), mIspdb( 0 ), mSetupManager( parent->setupManager() )
{
QWidget *pageParent = this;
ui.setupUi( pageParent );
KPIMUtils::EmailValidator* emailValidator = new KPIMUtils::EmailValidator( this );
ui.emailEdit->setValidator( emailValidator );
// KEmailSettings defaults
ui.nameEdit->setText( mSetupManager->name() );
ui.emailEdit->setText( mSetupManager->email() );
slotTextChanged();
connect( ui.emailEdit, SIGNAL(textChanged(QString)), SLOT(slotTextChanged()) );
connect( ui.nameEdit, SIGNAL(textChanged(QString)), SLOT(slotTextChanged()) );
connect( ui.createAccountPb, SIGNAL(clicked()), SLOT(slotCreateAccountClicked()) );
connect( ui.buttonGroup, SIGNAL(buttonClicked(QAbstractButton*)), SLOT(slotRadioButtonClicked(QAbstractButton*)) );
#ifdef KDEPIM_ENTERPRISE_BUILD
ui.checkOnlineGroupBox->setChecked( false );
#endif
}
void PersonalDataPage::setHideOptionInternetSearch( bool hide )
{
ui.checkOnlineGroupBox->setChecked( !hide );
ui.checkOnlineGroupBox->setVisible( !hide );
}
void PersonalDataPage::slotRadioButtonClicked( QAbstractButton* button)
{
QString smptHostname;
if ( !mIspdb->smtpServers().isEmpty() ) {
server s = mIspdb->smtpServers().first();
smptHostname = s.hostname;
}
ui.outgoingLabel->setText( i18n( "SMTP, %1", smptHostname ) );
if ( button == ui.imapAccount ) {
server simap = mIspdb->imapServers().first(); // should be ok.
ui.incommingLabel->setText( i18n( "IMAP, %1", simap.hostname ) );
ui.usernameLabel->setText( simap.username );
} else if ( button == ui.pop3Account ) {
server spop3 = mIspdb->pop3Servers().first(); // should be ok.
ui.incommingLabel->setText( i18n( "POP3, %1", spop3.hostname ) );
ui.usernameLabel->setText( spop3.username );
}
}
void PersonalDataPage::slotCreateAccountClicked()
{
configureSmtpAccount();
if ( ui.imapAccount->isChecked() )
configureImapAccount();
else
configurePop3Account();
emit leavePageNextOk(); // go to the next page
mSetupManager->execute();
}
void PersonalDataPage::slotTextChanged()
{
// Ignore the password field, as that can be empty when auth is based on ip-address.
setValid( !ui.emailEdit->text().isEmpty() &&
!ui.nameEdit->text().isEmpty() &&
KPIMUtils::isValidSimpleAddress( ui.emailEdit->text() ) );
}
void PersonalDataPage::leavePageNext()
{
ui.stackedPage->setCurrentIndex( 0 );
ui.imapAccount->setChecked( true );
mSetupManager->setPersonalDataAvailable( true );
mSetupManager->setName( ui.nameEdit->text() );
mSetupManager->setPassword( ui.passwordEdit->text() );
mSetupManager->setEmail( ui.emailEdit->text().trimmed() );
if ( ui.checkOnlineGroupBox->isChecked() ) {
// since the user can go back and forth, explicitly disable the man page
emit manualWanted( false );
setCursor( Qt::BusyCursor );
ui.mProgress->start();
kDebug() << "Searching on internet";
delete mIspdb;
mIspdb = new Ispdb( this );
connect(mIspdb, SIGNAL(searchType(QString)), this, SLOT(slotSearchType(QString)));
mIspdb->setEmail( ui.emailEdit->text() );
mIspdb->start();
connect( mIspdb, SIGNAL(finished(bool)),
SLOT(ispdbSearchFinished(bool)) );
} else {
emit manualWanted( true ); // enable the manual page
emit leavePageNextOk(); // go to the next page
}
}
void PersonalDataPage::ispdbSearchFinished( bool ok )
{
kDebug() << ok;
unsetCursor();
ui.mProgress->stop();
if ( ok ) {
if ( !mIspdb->imapServers().isEmpty() && !mIspdb->pop3Servers().isEmpty() )
{
ui.stackedPage->setCurrentIndex( 1 );
slotRadioButtonClicked( ui.imapAccount );
}
else
automaticConfigureAccount();
} else {
emit manualWanted( true ); // enable the manual page
emit leavePageNextOk();
}
}
void PersonalDataPage::slotSearchType(const QString &type)
{
ui.mProgress->setActiveLabel(type);
}
void PersonalDataPage::configureSmtpAccount()
{
if ( !mIspdb->smtpServers().isEmpty() ) {
server s = mIspdb->smtpServers().first(); // should be ok.
kDebug() << "Configuring transport for" << s.hostname;
QObject* object = mSetupManager->createTransport( QLatin1String("smtp") );
Transport* t = qobject_cast<Transport*>( object );
t->setName( accountName(mIspdb,s.username) );
t->setHost( s.hostname );
t->setPort( s.port );
t->setUsername( s.username );
t->setPassword( ui.passwordEdit->text() );
switch ( s.authentication ) {
case Ispdb::Plain: t->setAuthenticationType( QLatin1String("plain") ); break;
case Ispdb::CramMD5: t->setAuthenticationType( QLatin1String("cram-md5") ); break;
case Ispdb::NTLM: t->setAuthenticationType( QLatin1String("ntlm") ); break;
case Ispdb::GSSAPI: t->setAuthenticationType( QLatin1String("gssapi") ); break;
case Ispdb::ClientIP: break;
case Ispdb::NoAuth: break;
default: break;
}
switch ( s.socketType ) {
case Ispdb::Plain: t->setEncryption( QLatin1String("none") );break;
case Ispdb::SSL: t->setEncryption( QLatin1String("ssl") );break;
case Ispdb::StartTLS: t->setEncryption( QLatin1String("tls") );break;
default: break;
}
} else
kDebug() << "No transport to be created....";
}
void PersonalDataPage::configureImapAccount()
{
if ( !mIspdb->imapServers().isEmpty() ) {
server s = mIspdb->imapServers().first(); // should be ok.
kDebug() << "Configuring imap for" << s.hostname;
QObject* object = mSetupManager->createResource( QLatin1String("akonadi_imap_resource") );
Resource* t = qobject_cast<Resource*>( object );
t->setName( accountName(mIspdb,s.username) );
t->setOption( QLatin1String("ImapServer"), s.hostname );
t->setOption( QLatin1String("ImapPort"), s.port );
t->setOption( QLatin1String("UserName"), s.username );
t->setOption( QLatin1String("Password"), ui.passwordEdit->text() );
switch ( s.authentication ) {
case Ispdb::Plain: t->setOption( QLatin1String("Authentication"), MailTransport::Transport::EnumAuthenticationType::CLEAR ); break;
case Ispdb::CramMD5: t->setOption( QLatin1String("Authentication"), MailTransport::Transport::EnumAuthenticationType::CRAM_MD5 ); break;
case Ispdb::NTLM: t->setOption( QLatin1String("Authentication"), MailTransport::Transport::EnumAuthenticationType::NTLM ); break;
case Ispdb::GSSAPI: t->setOption( QLatin1String("Authentication"), MailTransport::Transport::EnumAuthenticationType::GSSAPI ); break;
case Ispdb::ClientIP: break;
case Ispdb::NoAuth: break;
default: break;
}
switch ( s.socketType ) {
case Ispdb::None: t->setOption( QLatin1String("Safety"), QLatin1String("None") );break;
case Ispdb::SSL: t->setOption( QLatin1String("Safety"), QLatin1String("SSL") );break;
case Ispdb::StartTLS: t->setOption( QLatin1String("Safety"), QLatin1String("STARTTLS") );break;
default: break;
}
}
}
void PersonalDataPage::configurePop3Account()
{
if ( !mIspdb->pop3Servers().isEmpty() ) {
server s = mIspdb->pop3Servers().first(); // should be ok.
kDebug() << "No Imap to be created, configuring pop3 for" << s.hostname;
QObject* object = mSetupManager->createResource( QLatin1String("akonadi_pop3_resource") );
Resource* t = qobject_cast<Resource*>( object );
t->setName( accountName(mIspdb,s.username) );
t->setOption( QLatin1String("Host"), s.hostname );
t->setOption( QLatin1String("Port"), s.port );
t->setOption( QLatin1String("Login"), s.username );
t->setOption( QLatin1String("Password"), ui.passwordEdit->text() );
switch ( s.authentication ) {
case Ispdb::Plain: t->setOption( QLatin1String("AuthenticationMethod"), MailTransport::Transport::EnumAuthenticationType::PLAIN ); break;
case Ispdb::CramMD5: t->setOption( QLatin1String("AuthenticationMethod"), MailTransport::Transport::EnumAuthenticationType::CRAM_MD5 ); break;
case Ispdb::NTLM: t->setOption( QLatin1String("AuthenticationMethod"), MailTransport::Transport::EnumAuthenticationType::NTLM ); break;
case Ispdb::GSSAPI: t->setOption( QLatin1String("AuthenticationMethod"), MailTransport::Transport::EnumAuthenticationType::GSSAPI ); break;
case Ispdb::ClientIP:
case Ispdb::NoAuth:
default: t->setOption( QLatin1String("AuthenticationMethod"), MailTransport::Transport::EnumAuthenticationType::CLEAR ); break;
}
switch ( s.socketType ) {
case Ispdb::SSL: t->setOption( QLatin1String("UseSSL"), 1 );break;
case Ispdb::StartTLS: t->setOption( QLatin1String("UseTLS"), 1 );break;
case Ispdb::None:
default: t->setOption( QLatin1String("UseTLS"), 1 ); break;
}
}
}
void PersonalDataPage::automaticConfigureAccount()
{
configureSmtpAccount();
configureImapAccount();
configurePop3Account();
emit leavePageNextOk(); // go to the next page
mSetupManager->execute();
}
void PersonalDataPage::leavePageNextRequested()
{
// override base class with doing nothing...
}

View file

@ -0,0 +1,64 @@
/*
Copyright (c) 2009 Volker Krause <vkrause@kde.org>
Copyright (c) 2010 Tom Albers <toma@kde.org>
Copyright (c) 2012 Laurent Montel <montel@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 PERSONALDATA_H
#define PERSONALDATA_H
#include "page.h"
#include "setupmanager.h"
#include "dialog.h"
#include "ui_personaldatapage.h"
class Ispdb;
class PersonalDataPage : public Page
{
Q_OBJECT
public:
explicit PersonalDataPage( Dialog* parent = 0 );
void setHideOptionInternetSearch( bool );
virtual void leavePageNext();
virtual void leavePageNextRequested();
private slots:
void ispdbSearchFinished( bool ok );
void slotTextChanged();
void slotCreateAccountClicked();
void slotRadioButtonClicked( QAbstractButton* button);
void slotSearchType(const QString&);
signals:
void manualWanted( bool );
private:
void automaticConfigureAccount();
void configureSmtpAccount();
void configureImapAccount();
void configurePop3Account();
Ui::PersonalDataPage ui;
Ispdb* mIspdb;
SetupManager *mSetupManager;
};
#endif

View file

@ -0,0 +1,110 @@
/*
Copyright (c) 2009 Volker Krause <vkrause@kde.org>
Copyright (c) 2010 Tom Albers <toma@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 "providerpage.h"
#include "global.h"
#include <KDebug>
#include <QSortFilterProxyModel>
ProviderPage::ProviderPage(KAssistantDialog* parent) :
Page( parent ),
m_model( new QStandardItemModel( this ) ),
m_newPageWanted( false ),
m_newPageReady( false )
{
ui.setupUi( this );
QSortFilterProxyModel *proxy = new QSortFilterProxyModel( this );
proxy->setSourceModel( m_model );
ui.listView->setModel( proxy );
ui.searchLine->setProxy( proxy );
m_fetchItem = new QStandardItem( i18n( "Fetching provider list..." ) );
m_fetchItem->setFlags(Qt::NoItemFlags);
m_model->appendRow( m_fetchItem );
connect( ui.listView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), SLOT(selectionChanged()) );
kDebug();
}
void ProviderPage::selectionChanged()
{
if ( ui.listView->selectionModel()->hasSelection() ) {
setValid( true );
} else {
setValid( false );
}
}
void ProviderPage::leavePageNext()
{
m_newPageReady = false;
if ( !ui.listView->selectionModel()->hasSelection() )
return;
const QModelIndex index = ui.listView->selectionModel()->selectedIndexes().first();
if ( !index.isValid() )
return;
const QSortFilterProxyModel *proxy = static_cast<const QSortFilterProxyModel*>( ui.listView->model() );
const QStandardItem* item = m_model->itemFromIndex( proxy->mapToSource( index ) );
kDebug() << "Item selected:"<< item->text();
}
void ProviderPage::findDesktopAndSetAssistant( const QStringList& list )
{
foreach ( const QString& file, list ) {
kDebug() << file;
if ( file.endsWith( QLatin1String ( ".desktop" ) ) ) {
kDebug() << "Yay, a desktop file!" << file;
Global::setAssistant( file );
m_newPageReady = true;
if ( m_newPageWanted ) {
kDebug() << "New page was already requested, now we are done, approve it";
emit leavePageNextOk();
}
break;
}
}
}
QTreeView *ProviderPage::treeview() const
{
return ui.listView;
}
void ProviderPage::leavePageBackRequested()
{
emit leavePageBackOk();
}
void ProviderPage::leavePageNextRequested()
{
m_newPageWanted = true;
if ( m_newPageReady ) {
kDebug() << "New page requested and we are done, so ok...";
emit leavePageNextOk();
} else {
kDebug() << "New page requested, but we are not done yet...";
}
}

View file

@ -0,0 +1,60 @@
/*
Copyright (c) 2009 Volker Krause <vkrause@kde.org>
Copyright (c) 2010 Tom Albers <toma@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 PROVIDERPAGE_H
#define PROVIDERPAGE_H
#include "page.h"
#include <QStandardItemModel>
#include "ui_providerpage.h"
struct Provider {
QString entryId;
QString entryProviderId;
};
class ProviderPage : public Page
{
Q_OBJECT
public:
explicit ProviderPage( KAssistantDialog* parent = 0 );
virtual void leavePageNext();
virtual void leavePageNextRequested();
virtual void leavePageBackRequested();
QTreeView *treeview() const;
private slots:
void selectionChanged();
private:
void findDesktopAndSetAssistant( const QStringList& list );
Ui::ProviderPage ui;
QStandardItemModel *m_model;
QStandardItem *m_fetchItem;
Provider m_wantedProvider;
bool m_newPageWanted;
bool m_newPageReady;
};
#endif

View file

@ -0,0 +1,165 @@
/*
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.
*/
#include "resource.h"
#include <akonadi/agenttype.h>
#include <akonadi/agentmanager.h>
#include <akonadi/agentinstancecreatejob.h>
#include <KDebug>
#include <KLocalizedString>
#include <QMetaMethod>
#include <QVariant>
#include <QtDBus/qdbusinterface.h>
#include <QtDBus/qdbusreply.h>
using namespace Akonadi;
static QVariant::Type argumentType( const QMetaObject *mo, const QString &method )
{
QMetaMethod m;
for ( int i = 0; i < mo->methodCount(); ++i ) {
const QString signature = QString::fromLatin1( mo->method( i ).signature() );
if ( signature.contains( method + QLatin1Char( '(' ) ) ) {
m = mo->method( i );
break;
}
}
if ( !m.signature() ) {
kWarning() << "Did not find D-Bus method: " << method << " available methods are:";
for ( int i = 0; i < mo->methodCount(); ++i )
kWarning() << mo->method( i ).signature();
return QVariant::Invalid;
}
const QList<QByteArray> argTypes = m.parameterTypes();
if ( argTypes.count() != 1 )
return QVariant::Invalid;
return QVariant::nameToType( argTypes.first() );
}
Resource::Resource(const QString& type, QObject* parent) :
SetupObject( parent ),
m_typeIdentifier( type )
{
}
void Resource::setOption( const QString &key, const QVariant &value )
{
m_settings.insert( key, value );
}
void Resource::setName( const QString &name )
{
m_name = name;
}
void Resource::create()
{
const AgentType type = AgentManager::self()->type( m_typeIdentifier );
if ( !type.isValid() ) {
emit error( i18n( "Resource type '%1' is not available.", m_typeIdentifier ) );
return;
}
// check if unique instance already exists
kDebug() << type.capabilities();
if ( type.capabilities().contains( QLatin1String( "Unique" ) ) ) {
foreach ( const AgentInstance &instance, AgentManager::self()->instances() ) {
kDebug() << instance.type().identifier() << ( instance.type() == type );
if ( instance.type() == type ) {
emit finished( i18n( "Resource '%1' is already set up.", type.name() ) );
return;
}
}
}
emit info( i18n( "Creating resource instance for '%1'...", type.name() ) );
AgentInstanceCreateJob *job = new AgentInstanceCreateJob( type, this );
connect( job, SIGNAL(result(KJob*)), SLOT(instanceCreateResult(KJob*)) );
job->start();
}
void Resource::instanceCreateResult(KJob* job)
{
if ( job->error() ) {
emit error( i18n( "Failed to create resource instance: %1", job->errorText() ) );
return;
}
m_instance = qobject_cast<AgentInstanceCreateJob*>( job )->instance();
if ( !m_settings.isEmpty() ) {
emit info( i18n( "Configuring resource instance..." ) );
QDBusInterface iface( QLatin1String("org.freedesktop.Akonadi.Resource.") + m_instance.identifier(), QLatin1String("/Settings") );
if ( !iface.isValid() ) {
emit error( i18n( "Unable to configure resource instance." ) );
return;
}
// configure resource
if ( !m_name.isEmpty() )
m_instance.setName( m_name );
QMap<QString, QVariant>::const_iterator end( m_settings.constEnd() );
for ( QMap<QString, QVariant>::const_iterator it = m_settings.constBegin(); it != end; ++it ) {
kDebug() << "Setting up " << it.key() << " for agent " << m_instance.identifier();
const QString methodName = QString::fromLatin1( "set%1" ).arg( it.key() );
QVariant arg = it.value();
const QVariant::Type targetType = argumentType( iface.metaObject(), methodName );
if ( !arg.canConvert( targetType ) ) {
emit error( i18n( "Could not convert value of setting '%1' to required type %2.", it.key(), QLatin1String(QVariant::typeToName( targetType )) ) );
return;
}
arg.convert( targetType );
QDBusReply<void> reply = iface.call( methodName, arg );
if ( !reply.isValid() ) {
emit error( i18n( "Could not set setting '%1': %2", it.key(), reply.error().message() ) );
return;
}
}
m_instance.reconfigure();
}
emit finished( i18n( "Resource setup completed." ) );
}
void Resource::destroy()
{
if ( m_instance.isValid() ) {
AgentManager::self()->removeInstance( m_instance );
emit info( i18n( "Removed resource instance for '%1'.", m_instance.type().name() ) );
}
}
QString Resource::identifier()
{
return m_instance.identifier();
}
void Resource::reconfigure()
{
m_instance.reconfigure();
}

View file

@ -0,0 +1,51 @@
/*
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 RESOURCE_H
#define RESOURCE_H
#include "setupobject.h"
#include <akonadi/agentinstance.h>
#include <QtCore/QMap>
class KJob;
class Resource : public SetupObject
{
Q_OBJECT
public:
explicit Resource( const QString &type, QObject *parent = 0 );
void create();
void destroy();
public slots:
Q_SCRIPTABLE void setName( const QString &name );
Q_SCRIPTABLE void setOption( const QString &key, const QVariant &value );
Q_SCRIPTABLE QString identifier();
Q_SCRIPTABLE void reconfigure();
private slots:
void instanceCreateResult( KJob* job );
private:
QString m_typeIdentifier, m_name;
QMap<QString, QVariant> m_settings;
Akonadi::AgentInstance m_instance;
};
#endif

View file

@ -0,0 +1,64 @@
/*
Copyright (c) 2010 Tom Albers <toma@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 "servertest.h"
#include <mailtransport/transport.h>
#include <mailtransport/servertest.h>
#include <kdebug.h>
#include <kmessagebox.h>
#include <klocale.h>
ServerTest::ServerTest( QObject* parent) :
QObject(parent), m_serverTest( new MailTransport::ServerTest( 0 ) )
{
kDebug() << "Welcome!";
connect( m_serverTest, SIGNAL(finished(QList<int>)),
SLOT(testFinished(QList<int>)) );
}
ServerTest::~ServerTest()
{
delete m_serverTest;
}
void ServerTest::test( const QString server, const QString protocol )
{
kDebug() << server << protocol;
m_serverTest->setServer( server );
m_serverTest->setProtocol( protocol );
m_serverTest->start();
}
void ServerTest::testFinished( QList< int > list )
{
kDebug() << "types: " << list;
if ( list.contains( MailTransport::Transport::EnumEncryption::TLS ) ) {
emit testResult( QLatin1String("tls") );
} else if ( list.contains( MailTransport::Transport::EnumEncryption::SSL ) ) {
emit testResult( QLatin1String("ssl") );
} else {
KMessageBox::information( 0, i18n( "There seems to be a problem in reaching this server "
"or choosing a safe way to sent the credentials to server. We advise you to "
"check the settings of the account and adjust it manually if needed." ),
i18n( "Autodetecting settings failed" ) );
emit testFail();
}
}

View file

@ -0,0 +1,54 @@
/*
Copyright (c) 2010 Tom Albers <toma@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 SERVERTEST_H
#define SERVERTEST_H
#include <QtCore/QObject>
namespace MailTransport {
class ServerTest;
}
class ServerTest : public QObject
{
Q_OBJECT
public:
explicit ServerTest( QObject *parent );
~ServerTest();
public slots:
/* @p protocol being 'imap' 'smtp' or 'pop3' */
Q_SCRIPTABLE void test( const QString server, const QString protocol );
signals:
/* returns the advised setting, @p result begin 'ssl' 'tls' or 'none'. */
void testResult( const QString& result );
/* returns if no connection is possible, test failed. */
void testFail();
private slots:
void testFinished( QList< int > list );
private:
MailTransport::ServerTest* m_serverTest;
};
#endif

View file

@ -0,0 +1,245 @@
/*
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.
*/
#include "setupmanager.h"
#include "resource.h"
#include "setuppage.h"
#include "transport.h"
#include "configfile.h"
#include "ldap.h"
#include "identity.h"
#include <kemailsettings.h>
#include <kwallet.h>
SetupManager::SetupManager( QWidget* parent) :
QObject(parent),
m_currentSetupObject( 0 ),
m_page( 0 ),
m_wallet( 0 ),
m_personalDataAvailable( false ),
m_rollbackRequested( false )
{
KEMailSettings e;
m_name = e.getSetting( KEMailSettings::RealName );
m_email = e.getSetting( KEMailSettings::EmailAddress );
}
SetupManager::~SetupManager()
{
delete m_wallet;
}
void SetupManager::setSetupPage(SetupPage* page)
{
m_page = page;
}
QObject* SetupManager::createResource(const QString& type)
{
return connectObject( new Resource( type, this ) );
}
QObject* SetupManager::createTransport(const QString& type)
{
return connectObject( new Transport( type, this ) );
}
QObject* SetupManager::createConfigFile(const QString& fileName)
{
return connectObject( new ConfigFile( fileName, this ) );
}
QObject* SetupManager::createLdap()
{
return connectObject( new Ldap( this ) );
}
QObject* SetupManager::createIdentity()
{
return connectObject( new Identity( this ) );
}
static bool dependencyCompare( SetupObject *left, SetupObject *right )
{
if ( !left->dependsOn() && right->dependsOn() )
return true;
return false;
}
void SetupManager::execute()
{
m_page->setStatus( i18n( "Setting up account..." ) );
m_page->setValid( false );
// ### FIXME this is a bad over-simplification and would need a real topological sort
// but for current usage it is good enough
qStableSort( m_objectToSetup.begin(), m_objectToSetup.end(), dependencyCompare );
setupNext();
}
void SetupManager::setupSucceeded(const QString& msg)
{
Q_ASSERT( m_page );
m_page->addMessage( SetupPage::Success, msg );
if(m_currentSetupObject) {
m_setupObjects.append( m_currentSetupObject );
m_currentSetupObject = 0;
}
setupNext();
}
void SetupManager::setupFailed(const QString& msg)
{
Q_ASSERT( m_page );
m_page->addMessage( SetupPage::Error, msg );
if( m_currentSetupObject ) {
m_setupObjects.append( m_currentSetupObject );
m_currentSetupObject = 0;
}
rollback();
}
void SetupManager::setupInfo(const QString& msg)
{
Q_ASSERT( m_page );
m_page->addMessage( SetupPage::Info, msg );
}
void SetupManager::setupNext()
{
// user canceld during the previous setup step
if ( m_rollbackRequested ) {
rollback();
return;
}
if ( m_objectToSetup.isEmpty() ) {
m_page->setStatus( i18n( "Setup complete." ) );
m_page->setProgress( 100 );
m_page->setValid( true );
} else {
const int setupObjectCount = m_objectToSetup.size() + m_setupObjects.size();
const int remainingObjectCount = setupObjectCount - m_objectToSetup.size();
m_page->setProgress( ( remainingObjectCount * 100 ) / setupObjectCount );
m_currentSetupObject = m_objectToSetup.takeFirst();
m_currentSetupObject->create();
}
}
void SetupManager::rollback()
{
m_page->setStatus( i18n( "Failed to set up account, rolling back..." ) );
const int setupObjectCount = m_objectToSetup.size() + m_setupObjects.size();
int remainingObjectCount = m_setupObjects.size();
foreach ( SetupObject* obj, m_setupObjects ) {
m_page->setProgress( ( remainingObjectCount * 100 ) / setupObjectCount );
if( obj ) {
obj->destroy();
m_objectToSetup.prepend( obj );
}
}
m_setupObjects.clear();
m_page->setProgress( 0 );
m_page->setStatus( i18n( "Failed to set up account." ) );
m_page->setValid( true );
m_rollbackRequested = false;
emit rollbackComplete();
}
SetupObject* SetupManager::connectObject(SetupObject* obj)
{
connect( obj, SIGNAL(finished(QString)), SLOT(setupSucceeded(QString)) );
connect( obj, SIGNAL(info(QString)), SLOT(setupInfo(QString)) );
connect( obj, SIGNAL(error(QString)), SLOT(setupFailed(QString)) );
m_objectToSetup.append( obj );
return obj;
}
void SetupManager::setName( const QString& name )
{
m_name = name;
}
QString SetupManager::name()
{
return m_name;
}
void SetupManager::setEmail( const QString& email)
{
m_email = email;
}
QString SetupManager::email()
{
return m_email;
}
void SetupManager::setPassword( const QString& password)
{
m_password = password;
}
QString SetupManager::password()
{
return m_password;
}
QString SetupManager::country()
{
return KGlobal::locale()->country();
}
void SetupManager::openWallet()
{
using namespace KWallet;
if ( Wallet::isOpen( Wallet::NetworkWallet() ) )
return;
Q_ASSERT( parent()->isWidgetType() );
m_wallet = Wallet::openWallet( Wallet::NetworkWallet(), qobject_cast<QWidget*>( parent() )->effectiveWinId(), Wallet::Asynchronous );
QEventLoop loop;
connect( m_wallet, SIGNAL(walletOpened(bool)), &loop, SLOT(quit()) );
loop.exec();
}
bool SetupManager::personalDataAvailable()
{
return m_personalDataAvailable;
}
void SetupManager::setPersonalDataAvailable(bool available)
{
m_personalDataAvailable = available;
}
void SetupManager::requestRollback()
{
if ( m_setupObjects.isEmpty() ) {
emit rollbackComplete();
} else {
m_rollbackRequested = true;
if ( !m_currentSetupObject )
rollback();
}
}

View file

@ -0,0 +1,86 @@
/*
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 SETUPMANAGER_H
#define SETUPMANAGER_H
#include <QtCore/QObject>
namespace KWallet {
class Wallet;
}
class SetupObject;
class SetupPage;
class SetupManager : public QObject
{
Q_OBJECT
public:
explicit SetupManager( QWidget *parent );
~SetupManager();
void setSetupPage( SetupPage* page );
void setName( const QString& );
void setEmail( const QString& );
void setPassword( const QString& );
void setPersonalDataAvailable( bool available );
public slots:
Q_SCRIPTABLE bool personalDataAvailable();
Q_SCRIPTABLE QString name();
Q_SCRIPTABLE QString email();
Q_SCRIPTABLE QString password();
Q_SCRIPTABLE QString country();
/** Ensures the wallet is open for subsequent sync wallet access in the resources. */
Q_SCRIPTABLE void openWallet();
Q_SCRIPTABLE QObject* createResource( const QString &type );
Q_SCRIPTABLE QObject* createTransport( const QString &type );
Q_SCRIPTABLE QObject* createConfigFile( const QString &configName );
Q_SCRIPTABLE QObject* createLdap();
Q_SCRIPTABLE QObject* createIdentity();
Q_SCRIPTABLE void execute();
void requestRollback();
signals:
void rollbackComplete();
private:
void setupNext();
void rollback();
SetupObject* connectObject( SetupObject* obj );
private slots:
void setupSucceeded( const QString &msg );
void setupFailed( const QString &msg );
void setupInfo( const QString &msg );
private:
QString m_name, m_email, m_password;
QList<SetupObject*> m_objectToSetup;
QList<SetupObject*> m_setupObjects;
SetupObject* m_currentSetupObject;
SetupPage* m_page;
KWallet::Wallet *m_wallet;
bool m_personalDataAvailable;
bool m_rollbackRequested;
};
#endif

View file

@ -0,0 +1,35 @@
/*
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.
*/
#include "setupobject.h"
SetupObject::SetupObject(QObject* parent): QObject(parent), m_dependsOn( 0 )
{
}
SetupObject* SetupObject::dependsOn() const
{
return m_dependsOn;
}
void SetupObject::setDependsOn(SetupObject* obj)
{
m_dependsOn = obj;
}

View file

@ -0,0 +1,46 @@
/*
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 SETUPOBJECT_H
#define SETUPOBJECT_H
#include <QtCore/QObject>
class SetupObject : public QObject
{
Q_OBJECT
public:
explicit SetupObject( QObject *parent );
virtual void create() = 0;
virtual void destroy() = 0;
SetupObject* dependsOn() const;
void setDependsOn( SetupObject* obj );
signals:
void error( const QString &msg );
void info( const QString &msg );
void finished( const QString &msg );
private:
SetupObject *m_dependsOn;
};
#endif

View file

@ -0,0 +1,71 @@
/*
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.
*/
#include "setuppage.h"
#include <qstandarditemmodel.h>
SetupPage::SetupPage(KAssistantDialog* parent) :
Page(parent),
m_msgModel( new QStandardItemModel( this ) )
{
ui.setupUi( this );
ui.detailView->setModel( m_msgModel );
connect( ui.detailsButton, SIGNAL(clicked()), SLOT(detailsClicked()) );
}
void SetupPage::enterPageNext()
{
ui.stackWidget->setCurrentIndex( 0 );
}
void SetupPage::detailsClicked()
{
ui.stackWidget->setCurrentIndex( 1 );
}
void SetupPage::addMessage(SetupPage::MessageType type, const QString& msg)
{
QStandardItem *item = new QStandardItem;
item->setText( msg );
item->setEditable( false );
switch ( type ) {
case Success:
item->setIcon( KIcon( QLatin1String("dialog-ok") ) );
break;
case Info:
item->setIcon( KIcon( QLatin1String("dialog-information" )) );
break;
case Error:
item->setIcon( KIcon( QLatin1String("dialog-error") ) );
break;
}
m_msgModel->appendRow( item );
}
void SetupPage::setStatus(const QString& msg)
{
ui.progressLabel->setText( msg );
}
void SetupPage::setProgress(int percent)
{
ui.progressBar->setValue( percent );
}

View file

@ -0,0 +1,52 @@
/*
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 SETUPPAGE_H
#define SETUPPAGE_H
#include "page.h"
#include "ui_setuppage.h"
class QStandardItemModel;
class SetupPage : public Page
{
Q_OBJECT
public:
explicit SetupPage( KAssistantDialog *parent );
virtual void enterPageNext();
enum MessageType {
Success,
Info,
Error
};
void addMessage( MessageType type, const QString &msg );
void setStatus( const QString &msg );
void setProgress( int percent );
private slots:
void detailsClicked();
private:
Ui::SetupPage ui;
QStandardItemModel* m_msgModel;
};
#endif

View file

@ -0,0 +1,156 @@
/*
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.
*/
#include "transport.h"
#include <mailtransport/transportmanager.h>
#include <KDebug>
#include <KLocalizedString>
#define TABLE_SIZE x
template <typename T>
struct StringValueTable {
const char * name;
typename T::type value;
typedef typename T::type value_type;
};
static const StringValueTable<MailTransport::Transport::EnumType> transportTypeEnums[] = {
{ "smtp", MailTransport::Transport::EnumType::SMTP },
{ "sendmail", MailTransport::Transport::EnumType::Sendmail },
{ "akonadi", MailTransport::Transport::EnumType::Akonadi }
};
static const int transportTypeEnumsSize = sizeof( transportTypeEnums ) / sizeof ( *transportTypeEnums );
static const StringValueTable<MailTransport::Transport::EnumEncryption> encryptionEnum[] = {
{ "none", MailTransport::Transport::EnumEncryption::None },
{ "ssl", MailTransport::Transport::EnumEncryption::SSL },
{ "tls", MailTransport::Transport::EnumEncryption::TLS }
};
static const int encryptionEnumSize = sizeof( encryptionEnum ) / sizeof( *encryptionEnum );
static const StringValueTable<MailTransport::Transport::EnumAuthenticationType> authenticationTypeEnum[] = {
{ "login", MailTransport::Transport::EnumAuthenticationType::LOGIN },
{ "plain", MailTransport::Transport::EnumAuthenticationType::PLAIN },
{ "cram-md5", MailTransport::Transport::EnumAuthenticationType::CRAM_MD5 },
{ "digest-md5", MailTransport::Transport::EnumAuthenticationType::DIGEST_MD5 },
{ "gssapi", MailTransport::Transport::EnumAuthenticationType::GSSAPI },
{ "ntlm", MailTransport::Transport::EnumAuthenticationType::NTLM },
{ "apop", MailTransport::Transport::EnumAuthenticationType::APOP },
{ "clear", MailTransport::Transport::EnumAuthenticationType::CLEAR },
{ "anonymous", MailTransport::Transport::EnumAuthenticationType::ANONYMOUS }
};
static const int authenticationTypeEnumSize = sizeof( authenticationTypeEnum ) / sizeof( *authenticationTypeEnum );
template <typename T>
static typename T::value_type stringToValue( const T *table, const int tableSize, const QString &string )
{
const QString ref = string.toLower();
for ( int i = 0; i < tableSize; ++i ) {
if ( ref == QLatin1String( table[i].name ) )
return table[i].value;
}
return table[0].value; // TODO: error handling
}
Transport::Transport(const QString& type, QObject* parent) :
SetupObject( parent ),
m_transportId( -1 ),
m_port( -1 ),
m_encr( MailTransport::Transport::EnumEncryption::TLS ),
m_auth( MailTransport::Transport::EnumAuthenticationType::PLAIN )
{
m_transportType = stringToValue( transportTypeEnums, transportTypeEnumsSize, type );
if ( m_transportType == MailTransport::Transport::EnumType::SMTP )
m_port = 25;
}
void Transport::create()
{
emit info( i18n( "Setting up mail transport account..." ) );
MailTransport::Transport* mt = MailTransport::TransportManager::self()->createTransport();
mt->setName( m_name );
mt->setHost( m_host );
if ( m_port > 0 )
mt->setPort( m_port );
if ( !m_user.isEmpty() ) {
mt->setUserName( m_user );
mt->setRequiresAuthentication( true );
}
if ( !m_password.isEmpty() ) {
mt->setStorePassword( true );
mt->setPassword( m_password );
}
mt->setEncryption( m_encr );
mt->setAuthenticationType( m_auth );
m_transportId = mt->id();
mt->writeConfig();
MailTransport::TransportManager::self()->addTransport( mt );
MailTransport::TransportManager::self()->setDefaultTransport( mt->id() );
emit finished( i18n( "Mail transport account set up." ) );
}
void Transport::destroy()
{
MailTransport::TransportManager::self()->removeTransport( m_transportId );
emit info( i18n( "Mail transport account deleted." ) );
}
void Transport::setName( const QString &name )
{
m_name = name;
}
void Transport::setHost( const QString &host )
{
m_host = host;
}
void Transport::setPort( int port )
{
m_port = port;
}
void Transport::setUsername( const QString &user )
{
m_user = user;
}
void Transport::setPassword( const QString &password )
{
m_password = password;
}
void Transport::setEncryption( const QString &encryption )
{
m_encr = stringToValue( encryptionEnum, encryptionEnumSize, encryption );
}
void Transport::setAuthenticationType( const QString &authType )
{
m_auth = stringToValue( authenticationTypeEnum, authenticationTypeEnumSize, authType );
}
int Transport::transportId() const
{
return m_transportId;
}

View file

@ -0,0 +1,62 @@
/*
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 TRANSPORT_H
#define TRANSPORT_H
#include "setupobject.h"
#include <mailtransport/transport.h>
class Transport : public SetupObject
{
Q_OBJECT
public:
explicit Transport( const QString &type, QObject *parent = 0 );
void create();
void destroy();
int transportId() const;
public slots:
Q_SCRIPTABLE void setName( const QString &name );
Q_SCRIPTABLE void setHost( const QString &host );
Q_SCRIPTABLE void setPort( int port );
Q_SCRIPTABLE void setUsername( const QString &user );
Q_SCRIPTABLE void setPassword( const QString &password );
Q_SCRIPTABLE void setEncryption( const QString &encryption );
Q_SCRIPTABLE void setAuthenticationType( const QString &authType );
private:
MailTransport::Transport::EnumEncryption stringToEncryption( const QString &encryptionString );
MailTransport::Transport::EnumAuthenticationType stringToAuthType( const QString &authString );
private:
int m_transportId;
MailTransport::Transport::EnumType::type m_transportType;
QString m_name;
QString m_host;
int m_port;
QString m_user;
QString m_password;
MailTransport::Transport::EnumEncryption::type m_encr;
MailTransport::Transport::EnumAuthenticationType::type m_auth;
};
#endif

View file

@ -0,0 +1,117 @@
/*
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.
*/
#include "typepage.h"
#include <KDebug>
#include <KDesktopFile>
#include <KStandardDirs>
#include <QSortFilterProxyModel>
#include "global.h"
#include <kmimetype.h>
TypePage::TypePage(KAssistantDialog* parent) :
Page( parent ),
m_model( new QStandardItemModel( this ) )
{
ui.setupUi( this );
#ifdef KDEPIM_MOBILE_UI
ui.label->setHidden( true );
ui.searchLine->setHidden( true );
#endif
#ifdef ACCOUNTWIZARD_NO_GHNS
ui.ghnsButton->hide();
#endif
QSortFilterProxyModel *proxy = new QSortFilterProxyModel( this );
proxy->setSourceModel( m_model );
ui.listView->setModel( proxy );
ui.searchLine->setProxy( proxy );
const QStringList list = KGlobal::dirs()->findAllResources( "data", QLatin1String( "akonadi/accountwizard/*.desktop" ),
KStandardDirs::Recursive | KStandardDirs::NoDuplicates );
const QStringList filter = Global::typeFilter();
foreach ( const QString &entry, list ) {
KDesktopFile f( entry );
kDebug() << entry << f.readName();
const KConfig configWizard( entry );
KConfigGroup grp( &configWizard, "Wizard" );
const QStringList lstType = grp.readEntry( "Type", QStringList() );
if ( lstType.isEmpty() ) {
kDebug() << QString::fromLatin1( " %1 doesn't contains specific type" ).arg( f.readName() );
}
if ( !filter.isEmpty() ) {
// stolen from agentfilterproxymodel
bool found = false;
foreach ( const QString &mimeType, lstType ) {
if ( filter.contains( mimeType ) ) {
found = true;
break;
} else {
foreach ( const QString &type, filter ) {
KMimeType::Ptr typePtr = KMimeType::mimeType( type, KMimeType::ResolveAliases );
if ( !typePtr.isNull() && typePtr->is( mimeType ) ) {
found = true;
break;
}
}
}
if ( found )
break;
}
if ( !found )
continue;
}
QStandardItem *item = new QStandardItem( f.readName() );
item->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled );
item->setData( entry, Qt::UserRole );
if ( !f.readIcon().isEmpty() )
item->setData( KIcon( f.readIcon() ), Qt::DecorationRole );
item->setData( f.readComment(), Qt::ToolTipRole );
m_model->appendRow( item );
}
connect( ui.listView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), SLOT(selectionChanged()) );
connect( ui.ghnsButton, SIGNAL(clicked()), SIGNAL(ghnsWanted()) );
}
void TypePage::selectionChanged()
{
if ( ui.listView->selectionModel()->hasSelection() ) {
setValid( true );
} else {
setValid( false );
}
}
void TypePage::leavePageNext()
{
if ( !ui.listView->selectionModel()->hasSelection() )
return;
const QModelIndex index = ui.listView->selectionModel()->selectedIndexes().first();
Global::setAssistant( index.data( Qt::UserRole ).toString() );
}
QTreeView *TypePage::treeview() const
{
return ui.listView;
}

View file

@ -0,0 +1,47 @@
/*
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 TYPEPAGE_H
#define TYPEPAGE_H
#include "page.h"
#include <QStandardItemModel>
#include "ui_typepage.h"
class TypePage : public Page
{
Q_OBJECT
public:
explicit TypePage( KAssistantDialog* parent = 0 );
virtual void leavePageNext();
QTreeView *treeview() const;
signals:
void ghnsWanted();
private slots:
void selectionChanged();
private:
Ui::TypePage ui;
QStandardItemModel *m_model;
};
#endif

View file

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>LoadPage</class>
<widget class="QWidget" name="LoadPage">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>84</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>129</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="statusLabel">
<property name="text">
<string>Loading assistant...</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>129</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View file

@ -0,0 +1,283 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>PersonalDataPage</class>
<widget class="QWidget" name="PersonalDataPage">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>521</width>
<height>289</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QLabel" name="welcomeLabel">
<property name="text">
<string>With a few simple steps we create the right settings for you. Please follow the steps of this wizard carefully.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="nameLabel">
<property name="text">
<string>Full name:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>nameEdit</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="KLineEdit" name="nameEdit">
<property name="minimumSize">
<size>
<width>0</width>
<height>22</height>
</size>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="emailLabel">
<property name="text">
<string>E-mail address:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>emailEdit</cstring>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="KLineEdit" name="emailEdit">
<property name="minimumSize">
<size>
<width>0</width>
<height>22</height>
</size>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="KLineEdit" name="passwordEdit">
<property name="minimumSize">
<size>
<width>0</width>
<height>22</height>
</size>
</property>
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="passwordLabel">
<property name="text">
<string>Password:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>passwordEdit</cstring>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QStackedWidget" name="stackedPage">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="internetPage">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QGroupBox" name="checkOnlineGroupBox">
<property name="title">
<string>Find provider settings on the Internet</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="checkOnlineExplanation">
<property name="text">
<string>Check online for the settings needed for this email provider. Only the domain name part of the e-mail address will be sent over the Internet at this point. If this option is unchecked, the account can be set up manually.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="KPIMUtils::ProgressIndicatorLabel" name="mProgress"/>
</item>
</layout>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="accountPage">
<layout class="QGridLayout" name="gridLayout_4">
<item row="0" column="0">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QRadioButton" name="imapAccount">
<property name="text">
<string>IMAP account</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
<attribute name="buttonGroup">
<string notr="true">buttonGroup</string>
</attribute>
</widget>
</item>
<item>
<widget class="QRadioButton" name="pop3Account">
<property name="text">
<string>POP3 account</string>
</property>
<attribute name="buttonGroup">
<string notr="true">buttonGroup</string>
</attribute>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Incoming:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="incommingLabel">
<property name="text">
<string comment="KDE::DoNotExtract">TextLabel</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Outgoing:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="outgoingLabel">
<property name="text">
<string comment="KDE::DoNotExtract">TextLabel</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Username:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="usernameLabel">
<property name="text">
<string comment="KDE::DoNotExtract">TextLabel</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="createAccountPb">
<property name="text">
<string>Create Account</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>KLineEdit</class>
<extends>QLineEdit</extends>
<header>klineedit.h</header>
</customwidget>
<customwidget>
<class>KPIMUtils::ProgressIndicatorLabel</class>
<extends>QLabel</extends>
<header location="global">kpimutils/progressindicatorlabel.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
<buttongroups>
<buttongroup name="buttonGroup"/>
</buttongroups>
</ui>

View file

@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ProviderPage</class>
<widget class="QWidget" name="ProviderPage">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>172</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Select your provider from the list below or click advanced if your provider is not listed</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="KFilterProxySearchLine" name="searchLine"/>
</item>
<item>
<widget class="QTreeView" name="listView">
<property name="rootIsDecorated">
<bool>false</bool>
</property>
<property name="uniformRowHeights">
<bool>true</bool>
</property>
<property name="sortingEnabled">
<bool>true</bool>
</property>
<property name="allColumnsShowFocus">
<bool>true</bool>
</property>
<property name="headerHidden">
<bool>true</bool>
</property>
<attribute name="headerShowSortIndicator" stdset="0">
<bool>true</bool>
</attribute>
<attribute name="headerShowSortIndicator" stdset="0">
<bool>true</bool>
</attribute>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>KFilterProxySearchLine</class>
<extends>QWidget</extends>
<header>kfilterproxysearchline.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View file

@ -0,0 +1,103 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SetupPage</class>
<widget class="QWidget" name="SetupPage">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>143</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QStackedWidget" name="stackWidget">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="page">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>109</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="progressLabel">
<property name="text">
<string>Setting up account...</string>
</property>
</widget>
</item>
<item>
<widget class="QProgressBar" name="progressBar"/>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="KPushButton" name="detailsButton">
<property name="text">
<string>&amp;Details...</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>74</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="page_2">
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QListView" name="detailView"/>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>KPushButton</class>
<extends>QPushButton</extends>
<header>kpushbutton.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View file

@ -0,0 +1,84 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>TypePage</class>
<widget class="QWidget" name="TypePage">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>151</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Select which kind of account you want to create:</string>
</property>
</widget>
</item>
<item>
<widget class="KFilterProxySearchLine" name="searchLine"/>
</item>
<item>
<widget class="QTreeView" name="listView">
<property name="rootIsDecorated">
<bool>false</bool>
</property>
<property name="uniformRowHeights">
<bool>true</bool>
</property>
<property name="sortingEnabled">
<bool>true</bool>
</property>
<property name="allColumnsShowFocus">
<bool>true</bool>
</property>
<property name="headerHidden">
<bool>true</bool>
</property>
<attribute name="headerShowSortIndicator" stdset="0">
<bool>true</bool>
</attribute>
<attribute name="headerShowSortIndicator" stdset="0">
<bool>true</bool>
</attribute>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="ghnsButton">
<property name="text">
<string>Check for more on Internet</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>KFilterProxySearchLine</class>
<extends>QWidget</extends>
<header>kfilterproxysearchline.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View file

@ -0,0 +1 @@
add_subdirectory(tine20)

View file

@ -0,0 +1,2 @@
install ( FILES tine20wizard.desktop tine20wizard.es tine20wizard.ui DESTINATION ${DATA_INSTALL_DIR}/akonadi/accountwizard/tine20 )

View file

@ -0,0 +1,4 @@
#! /usr/bin/env bash
$EXTRACTRC *.ui >> rc.cpp
$XGETTEXT *.cpp -o $podir/accountwizard_tine20.pot
$XGETTEXT -kqsTr *.es -j -o $podir/accountwizard_tine20.pot

View file

@ -0,0 +1,93 @@
[Desktop Entry]
Name=Tine 2.0 Groupware Server
Name[bs]=Tine 2.0 Groupware Server
Name[ca]=Servidor de treball en grup Tine 2.0
Name[ca@valencia]=Servidor de treball en grup Tine 2.0
Name[cs]=Groupware Server Tine 2.0
Name[da]=Tine 2.0 groupware-server
Name[de]=Tine 2.0 Groupware-Server
Name[el]=Tine 2.0 Groupware Server
Name[en_GB]=Tine 2.0 Groupware Server
Name[es]=Servidor de trabajo en grupo Tine 2.0
Name[et]=Tine 2.0 grupitöö server
Name[fi]=Tine 2.0 -työryhmäpalvelin
Name[fr]=Serveur de logiciels de collaboration Tine 2.0
Name[ga]=Freastalaí Groupware Tine 2.0
Name[gl]=Servidor de grupos Tine 2.0
Name[hu]=Tine 2.0 csoportmunka-kiszolgáló
Name[ia]=Servitor de Tine 2.0 Groupware
Name[it]=Server di groupware Tine 2.0
Name[kk]=Tine 2.0 топтық іс сервері
Name[km]= Tine . Groupware
Name[ko]=Tine 2.0
Name[lt]=Tine 2.0 grupinio darbo serveris
Name[lv]=Tine 2.0 grupprogrammatūras serveris
Name[nb]=Tine 2.0 gruppevare-tjener
Name[nds]=Tine 2.0-Arbeitkoppel-Server
Name[nl]=Tine 2.0 groupwareserver
Name[pl]=Serwer Groupware Tine 2.0
Name[pt]=Servidor de Groupware Tine 2.0
Name[pt_BR]=Servidor groupware Tine 2.0
Name[ru]=Сервер совместной работы Tine 2.0
Name[sk]=Tine 2.0 Groupware Server
Name[sl]=Strežnik Tine 2.0 za skupinsko delo
Name[sr]=Тинеов групверски сервер
Name[sr@ijekavian]=Тинеов групверски сервер
Name[sr@ijekavianlatin]=Tineov grupverski server
Name[sr@latin]=Tineov grupverski server
Name[sv]=Tine 2.0 grupprogramserver
Name[tr]=Tine 2.0 Groupware Sunucusu
Name[uk]=Сервер групової роботи Tine 2.0
Name[x-test]=xxTine 2.0 Groupware Serverxx
Name[zh_CN]=Tine 2.0
Name[zh_TW]=Tine 2.0
Icon=applications-internet
Comment=Tine 2.0 Groupware Server
Comment[bs]=Tine 2.0 Groupware Server
Comment[ca]=Servidor de treball en grup Tine 2.0
Comment[ca@valencia]=Servidor de treball en grup Tine 2.0
Comment[cs]=Groupware Server Tine 2.0
Comment[da]=Tine 2.0 groupware-server
Comment[de]=Tine 2.0 Groupware-Server
Comment[el]=Εξυπηρετητής Tine 2.0 Groupware
Comment[en_GB]=Tine 2.0 Groupware Server
Comment[es]=Servidor de trabajo en grupo Tine 2.0
Comment[et]=Tine 2.0 grupitöö server
Comment[fi]=Tine 2.0 -työryhmäpalvelin
Comment[fr]=Serveur de logiciels de collaboration Tine 2.0
Comment[ga]=Freastalaí Groupware Tine 2.0
Comment[gl]=Servidor de grupos Tine 2.0
Comment[hu]=Tine 2.0 csoportmunka-kiszolgáló
Comment[ia]=Servitor de Tine 2.0 Groupware
Comment[it]=Server di groupware Tine 2.0
Comment[kk]=Tine 2.0 топтық іс сервері
Comment[km]= Tine . Groupware
Comment[ko]=Tine 2.0
Comment[lt]=Tine 2.0 grupinio darbo serveris
Comment[lv]=Tine 2.0 grupprogrammatūras serveris
Comment[nb]=Tine 2.0 gruppevare-tjener
Comment[nds]=Tine 2.0-Arbeitkoppel-Server
Comment[nl]=Tine 2.0 groupwareserver
Comment[pl]=Serwer Groupware Tine 2.0
Comment[pt]=Servidor de 'Groupware' Tine 2.0
Comment[pt_BR]=Servidor groupware Tine 2.0
Comment[ru]=Сервер совместной работы Tine 2.0
Comment[sk]=Tine 2.0 Groupware Server
Comment[sl]=Strežnik Tine 2.0 za skupinsko delo
Comment[sr]=Тинеов групверски сервер
Comment[sr@ijekavian]=Тинеов групверски сервер
Comment[sr@ijekavianlatin]=Tineov grupverski server
Comment[sr@latin]=Tineov grupverski server
Comment[sv]=Tine 2.0 grupprogramserver
Comment[tr]=Tine 2.0 Groupware Sunucusu
Comment[uk]=Сервер групової роботи Tine 2.0
Comment[x-test]=xxTine 2.0 Groupware Serverxx
Comment[zh_CN]=Tine 2.0
Comment[zh_TW]=Tine 2.0
[Wizard]
Type=message/rfc822,text/directory,text/calendar
Script=tine20wizard.es
[Translate]
Filename=accountwizard_tine20

View file

@ -0,0 +1,177 @@
/*
Copyright (c) 2012 Volker Krause <vkrause@kde.org>
Copyright (c) 2010 Casey Link <unnamedrambler@gmail.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.
*/
// add this function to trim user input of whitespace when needed
String.prototype.trim = function() { return this.replace(/^\s+|\s+$/g, ""); };
var page = Dialog.addPage( "tine20wizard.ui", qsTr("Personal Settings") );
var userChangedServerAddress = false;
page.widget().nameEdit.text = SetupManager.name()
page.widget().emailEdit.text = SetupManager.email()
page.widget().passwordEdit.text = SetupManager.password()
guessServerName();
if ( SetupManager.personalDataAvailable() ) {
page.widget().nameEdit.visible = false;
page.widget().nameLabel.visible = false;
page.widget().emailEdit.visible = false;
page.widget().emailLabel.visible = false;
page.widget().passwordEdit.visible = false;
page.widget().passwordLabel.visible = false;
}
function guessServerName()
{
if ( userChangedServerAddress == true ) {
return;
}
var email = page.widget().emailEdit.text;
var pos = email.indexOf( "@" );
if ( pos >= 0 && (pos + 1) < email.length ) {
var server = email.slice( pos + 1, email.length );
page.widget().serverAddress.text = server;
}
userChangedServerAddress = false;
}
function emailChanged( arg )
{
validateInput();
guessServerName();
}
function serverChanged( arg )
{
validateInput();
if ( arg == "" ) {
userChangedServerAddress = false;
} else {
userChangedServerAddress = true;
}
}
function validateInput()
{
if ( page.widget().serverAddress.text.trim() == "" || page.widget().emailEdit.text.trim() == "" ) {
page.setValid( false );
} else {
page.setValid( true );
}
}
// stage 1, setup identity and run imap server test
// stage 2, smtp setup (no server test) and Dav resources
var stage = 1;
var identity; // global so it can be accesed in setup and testOk
function setup()
{
print("setup() " + stage);
var serverAddress = page.widget().serverAddress.text.trim();
if ( stage == 1 ) {
SetupManager.openWallet();
identity = SetupManager.createIdentity();
identity.setEmail( page.widget().emailEdit.text );
identity.setRealName( page.widget().nameEdit.text );
ServerTest.test( serverAddress, "imap" );
} else { // stage 2
var smtp = SetupManager.createTransport( "smtp" );
smtp.setName( serverAddress );
smtp.setHost( serverAddress );
smtp.setPort( 25 );
smtp.setEncryption( "TLS" );
smtp.setAuthenticationType( "plain" );
smtp.setUsername( page.widget().emailEdit.text );
smtp.setPassword( page.widget().passwordEdit.text );
identity.setTransport( smtp );
var dav = SetupManager.createResource( "akonadi_davgroupware_resource" );
print("dav: " + dav );
try {
dav.setName( "Tine 2.0" );
dav.setOption( "DisplayName", "Tine 2.0" );
dav.setOption( "RefreshInterval", 60 );
dav.setOption( "RemoteUrls", ["$default$|CalDav|https://" + page.widget().serverAddress.text.trim() + "/calendars",
"$default$|CardDav|https://" + page.widget().serverAddress.text.trim() + "/addressbooks"] );
dav.setOption( "DefaultUsername", page.widget().emailEdit.text.trim() );
} catch (e) { print(e); }
print("pre-exec");
SetupManager.execute();
print("post-exec");
}
}
function testResultFail()
{
testOk( -1 );
}
function testOk( arg )
{
print("testOk arg =", arg);
var imapRes = SetupManager.createResource( "akonadi_imap_resource" );
imapRes.setName( page.widget().serverAddress.text.trim() );
imapRes.setOption( "ImapServer", page.widget().serverAddress.text.trim() );
imapRes.setOption( "UserName", page.widget().emailEdit.text.trim() );
imapRes.setOption( "Password", page.widget().passwordEdit.text.trim() );
imapRes.setOption( "UseDefaultIdentity", false );
imapRes.setOption( "AccountIdentity", identity.uoid() );
imapRes.setOption( "DisconnectedModeEnabled", true );
imapRes.setOption( "IntervalCheckTime", 60 );
imapRes.setOption( "SubscriptionEnabled", true );
imapRes.setOption( "SieveSupport", false );
imapRes.setOption( "Authentication", 7 ); // ClearText
if ( arg == "ssl" ) {
// The ENUM used for authentication (in the imap resource only)
imapRes.setOption( "Safety", "SSL" ); // SSL/TLS
imapRes.setOption( "ImapPort", 993 );
} else if ( arg == "tls" ) { // tls is really STARTTLS
imapRes.setOption( "Safety", "STARTTLS" ); // STARTTLS
imapRes.setOption( "ImapPort", 143 );
} else if ( arg == "none" ) {
imapRes.setOption( "Safety", "NONE" ); // No encryption
imapRes.setOption( "ImapPort", 143 );
} else {
// safe default fallback in case server test failed
imapRes.setOption( "Safety", "STARTTLS" );
imapRes.setOption( "ImapPort", 143 );
}
stage = 2;
setup();
}
try {
ServerTest.testFail.connect(testResultFail);
ServerTest.testResult.connect(testOk);
page.widget().emailEdit.textChanged.connect(emailChanged);
page.widget().serverAddress.textChanged.connect(serverChanged);
page.pageLeftNext.connect(setup);
} catch (e) {
print(e);
}
validateInput();

View file

@ -0,0 +1,87 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>tine20Wizard</class>
<widget class="QWidget" name="tine20Wizard">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>368</width>
<height>124</height>
</rect>
</property>
<layout class="QFormLayout" name="formLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::ExpandingFieldsGrow</enum>
</property>
<item row="0" column="0">
<widget class="QLabel" name="nameLabel">
<property name="text">
<string>&amp;Name:</string>
</property>
<property name="buddy">
<cstring>nameEdit</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="KLineEdit" name="nameEdit"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="emailLabel">
<property name="text">
<string>&amp;Email:</string>
</property>
<property name="buddy">
<cstring>emailEdit</cstring>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="KLineEdit" name="emailEdit"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="passwordLabel">
<property name="text">
<string>&amp;Password:</string>
</property>
<property name="buddy">
<cstring>passwordEdit</cstring>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="KLineEdit" name="passwordEdit">
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>&amp;Server Address:</string>
</property>
<property name="buddy">
<cstring>serverAddress</cstring>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="KLineEdit" name="serverAddress"/>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>KLineEdit</class>
<extends>QLineEdit</extends>
<header>klineedit.h</header>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>serverAddress</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>

View file

@ -0,0 +1 @@
SKIP /ontologies/

View file

@ -0,0 +1,20 @@
add_definitions( -DQT_NO_CAST_FROM_ASCII )
add_definitions( -DQT_NO_CAST_TO_ASCII )
macro(kdepim_add_agent _target)
if(KDEPIM_BUILD_AGENTS_AS_PLUGINS)
add_definitions(-DKDEPIM_PLUGIN_AGENT)
kde4_add_plugin(${_target} ${ARGN})
install( TARGETS ${_target} DESTINATION ${PLUGIN_INSTALL_DIR}/ )
else()
kde4_add_executable(${_target} ${ARGN})
install(TARGETS ${_target} ${INSTALL_TARGETS_DEFAULT_ARGS})
endif()
endmacro()
add_subdirectory( maildispatcher )
add_subdirectory( newmailnotifier )
add_subdirectory( migration )
add_subdirectory( invitations )
install(FILES akonadinepomukfeederagent.desktop DESTINATION "${CMAKE_INSTALL_PREFIX}/share/akonadi/agents")

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>

View file

@ -0,0 +1,2 @@
// DOXYGEN_NAME=Akonadi Agents
// DOXYGEN_ENABLE=YES

View file

@ -0,0 +1,53 @@
[Desktop Entry]
Name=Akonadi Nepomuk Feeder
Name[bs]=Akonadi Nepomuk napajač
Name[ca]=Alimentador del Nepomuk per a l'Akonadi
Name[ca@valencia]=Alimentador del Nepomuk per a l'Akonadi
Name[cs]=Akonadi podavač Nepomuku
Name[da]=Akonadi Nepomuk-feeder
Name[de]=Nepomuk-Modul für Akonadi
Name[el]=Τροφοδότης Nepomuk του Akonadi
Name[en_GB]=Akonadi Nepomuk Feeder
Name[es]=Alimentador Nepomuk de Akonadi
Name[et]=Akonadi Nepomuki söötur
Name[fi]=Akonadi Nepomuk Feeder
Name[fr]=Connecteur Nepomuk pour Akonadi
Name[ga]=Fothaire Nepomuk Akonadi
Name[gl]=Alimentador de Nepomuk para Akonadi
Name[hu]=Akonadi Nepomuk feltöltő
Name[ia]=Syndication de Akonadi Nepomuk
Name[it]=Fornitore Akonadi per Nepomuk
Name[kk]=Nepomuk эл.пошта бергіші
Name[km]= Akonadi Nepomuk
Name[ko]=Akonadi Nepomuk
Name[lt]=Akonadi Nepomuk šaltinis
Name[lv]=Akonadi Nepomuk barotājs
Name[nb]=Akonadi innmating til Nepomuk
Name[nds]=Nepomuk-Ingaav för Akonadi
Name[nl]=Akonadi Nepumuk-feeder
Name[pl]=Podajnik Akonadi Nepomuk
Name[pt]=Fontes do Nepomuk para o Akonadi
Name[pt_BR]=Alimentador do Nepomuk para o Akonadi
Name[ru]=Akonadi Nepomuk Feeder
Name[sk]=Kŕmitko Nepomuk Akonadi
Name[sl]=Podajalnik za Nepomuk
Name[sr]=Непомуков уводник Аконадија
Name[sr@ijekavian]=Непомуков уводник Аконадија
Name[sr@ijekavianlatin]=Nepomukov uvodnik Akonadija
Name[sr@latin]=Nepomukov uvodnik Akonadija
Name[sv]=Akonadi-inmatning till Nepomuk
Name[tr]=Akonadi Nepomuk Besleyici
Name[uk]=Передавач даних Akonadi Nepomuk
Name[x-test]=xxAkonadi Nepomuk Feederxx
Name[zh_CN]=Akonadi Nepomuk
Name[zh_TW]=Akonadi Nepomuk Feeder
Type=AkonadiAgent
Exec=akonadi_nepomuk_feeder
Icon=nepomuk
# This agent is disabled, do not autostart it.
# KDE5: remove this file
X-Akonadi-MimeTypes=
X-Akonadi-Capabilities=
X-Akonadi-Identifier=akonadi_nepomuk_feeder

View file

@ -0,0 +1,35 @@
set( invitationsagent_SRCS
invitationsagent.cpp
incidenceattribute.cpp
)
#kde4_add_ui_files(invitationsagent_SRCS settings.ui)
#kde4_add_kcfg_files(invitationsagent_SRCS settings.kcfgc)
#kcfg_generate_dbus_interface(${CMAKE_CURRENT_SOURCE_DIR}/invitationsagent.kcfg org.kde.Akonadi.MailDispatcher.Settings)
#qt4_add_dbus_adaptor(invitationsagent_SRCS
# ${CMAKE_CURRENT_BINARY_DIR}/org.kde.Akonadi.MailDispatcher.Settings.xml settings.h Settings
#)
## qt4_add_dbus_adaptor( invitationsagent_SRCS
## ${KDE4_DBUS_INTERFACES_DIR}/org.kde.Akonadi.MailDispatcher.xml invitationsagent.h MailDispatcherAgent
## )
kde4_add_executable(akonadi_invitations_agent ${invitationsagent_SRCS})
target_link_libraries(akonadi_invitations_agent
${QT_QTCORE_LIBRARY} ${QT_QTDBUS_LIBRARY} ${KDE4_KDECORE_LIBS} ${KDE4_KIO_LIBS}
${KDEPIMLIBS_AKONADI_LIBS}
${KDEPIMLIBS_AKONADI_KMIME_LIBS}
${KDEPIMLIBS_KMIME_LIBS}
${KDEPIMLIBS_MAILTRANSPORT_LIBS}
${KDEPIMLIBS_KCALCORE_LIBS}
)
if (Q_WS_MAC)
set_target_properties(akonadi_invitations_agent PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/../Info.plist.template)
set_target_properties(akonadi_invitations_agent PROPERTIES MACOSX_BUNDLE_GUI_IDENTIFIER "org.kde.Akonadi.invitationsagent")
set_target_properties(akonadi_invitations_agent PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "KDE Akonadi Invitations Calendar")
endif ()
install(TARGETS akonadi_invitations_agent ${INSTALL_TARGETS_DEFAULT_ARGS})
install(FILES invitationsagent.desktop DESTINATION "${CMAKE_INSTALL_PREFIX}/share/akonadi/agents")

View file

@ -0,0 +1,3 @@
#! /bin/sh
$XGETTEXT *.cpp -o $podir/akonadi_invitations_agent.pot

View file

@ -0,0 +1,92 @@
/*
Copyright (c) 2009 Sebastian Sauer <sebsauer@kdab.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 "incidenceattribute.h"
#include <QtCore/QString>
#include <QtCore/QTextStream>
using namespace Akonadi;
class IncidenceAttribute::Private
{
public:
QString status;
Akonadi::Item::Id referenceId;
explicit Private() : referenceId( -1 ) {}
};
IncidenceAttribute::IncidenceAttribute()
: Attribute(), d( new Private )
{
}
IncidenceAttribute::~IncidenceAttribute()
{
delete d;
}
QByteArray IncidenceAttribute::type() const
{
return "incidence";
}
Attribute* IncidenceAttribute::clone() const
{
IncidenceAttribute *other = new IncidenceAttribute;
return other;
}
QByteArray IncidenceAttribute::serialized() const
{
QString data;
QTextStream out( &data );
out << d->status;
out << d->referenceId;
return data.toUtf8();
}
void IncidenceAttribute::deserialize( const QByteArray &data )
{
QString s( QString::fromUtf8( data ) );
QTextStream in( &s );
in >> d->status;
in >> d->referenceId;
}
QString IncidenceAttribute::status() const
{
return d->status;
}
void IncidenceAttribute::setStatus( const QString &newstatus ) const
{
d->status = newstatus;
}
Akonadi::Item::Id IncidenceAttribute::reference() const
{
return d->referenceId;
}
void IncidenceAttribute::setReference( Akonadi::Item::Id id )
{
d->referenceId = id;
}

View file

@ -0,0 +1,63 @@
/*
Copyright (c) 2009 Sebastian Sauer <sebsauer@kdab.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 INCIDENCEATTRIBUTE_H
#define INCIDENCEATTRIBUTE_H
#include <akonadi/item.h>
#include <akonadi/attribute.h>
namespace Akonadi {
class IncidenceAttribute : public Akonadi::Attribute
{
public:
explicit IncidenceAttribute();
~IncidenceAttribute();
virtual QByteArray type() const;
virtual Attribute* clone() const;
virtual QByteArray serialized() const;
virtual void deserialize( const QByteArray &data );
/**
* The status the invitation is in.
*
* One of;
* "new", "accepted", "tentative", "counter", "cancel", "reply", "delegated"
*/
QString status() const;
void setStatus( const QString &newstatus ) const;
/**
* The referenced item. This is used e.g. in the invitationagent to
* let users know where the original mail message is.
*/
Akonadi::Item::Id reference() const;
void setReference( Akonadi::Item::Id id );
private:
class Private;
Private *const d;
};
}
#endif

View file

@ -0,0 +1,560 @@
/*
Copyright 2009 Sebastian Sauer <sebsauer@kdab.net>
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 "invitationsagent.h"
#include "incidenceattribute.h"
#include <Akonadi/AgentInstance>
#include <Akonadi/AgentInstanceCreateJob>
#include <Akonadi/AgentManager>
#include <Akonadi/ChangeRecorder>
#include <Akonadi/Collection>
#include <Akonadi/CollectionCreateJob>
#include <Akonadi/CollectionFetchJob>
#include <Akonadi/CollectionFetchScope>
#include <Akonadi/ItemFetchJob>
#include <Akonadi/ItemFetchScope>
#include <Akonadi/ItemModifyJob>
#include <akonadi/kmime/messageflags.h>
#include <akonadi/resourcesynchronizationjob.h>
#include <akonadi/specialcollections.h>
#include <akonadi/specialcollectionsrequestjob.h>
#include <kcalcore/event.h>
#include <kcalcore/icalformat.h>
#include <kcalcore/incidence.h>
#include <kcalcore/journal.h>
#include <kcalcore/todo.h>
#include <KConfig>
#include <KConfigSkeleton>
#include <KDebug>
#include <KJob>
#include <KLocalizedString>
#include <KMime/Content>
#include <KMime/Message>
#include <kpimidentities/identitymanager.h>
#include <KSystemTimeZones>
#include <KStandardDirs>
#include <QtCore/QFileInfo>
#include <QtCore/QTimer>
#include <QtDBus/QDBusInterface>
#include <QtDBus/QDBusReply>
using namespace Akonadi;
class InvitationsCollectionRequestJob : public SpecialCollectionsRequestJob
{
public:
InvitationsCollectionRequestJob( SpecialCollections* collection, InvitationsAgent *agent )
: SpecialCollectionsRequestJob( collection, agent )
{
setDefaultResourceType( QLatin1String( "akonadi_ical_resource" ) );
QVariantMap options;
options.insert( QLatin1String( "Path" ), QString( KGlobal::dirs()->localxdgdatadir() + QLatin1String( "akonadi_invitations" ) ) );
options.insert( QLatin1String( "Name" ), i18n( "Invitations" ) );
setDefaultResourceOptions( options );
QMap<QByteArray, QString> displayNameMap;
displayNameMap.insert( "invitations", i18n( "Invitations" ) );
setTypes( displayNameMap.keys() );
setNameForTypeMap( displayNameMap );
QMap<QByteArray, QString> iconNameMap;
iconNameMap.insert( "invitations", QLatin1String( "folder" ) );
setIconForTypeMap( iconNameMap );
}
virtual ~InvitationsCollectionRequestJob()
{
}
};
class InvitationsCollection : public SpecialCollections
{
public:
class Settings : public KCoreConfigSkeleton
{
public:
Settings()
{
setCurrentGroup( QLatin1String("Invitations") );
addItemString( QLatin1String("DefaultResourceId"), m_id, QString() );
}
virtual ~Settings()
{
}
private:
QString m_id;
};
InvitationsCollection( InvitationsAgent *agent )
: Akonadi::SpecialCollections( new Settings ), m_agent( agent ), sInvitationsType( "invitations" )
{
}
virtual ~InvitationsCollection()
{
}
void clear()
{
m_collection = Collection();
}
bool hasDefaultCollection() const
{
return SpecialCollections::hasDefaultCollection( sInvitationsType );
}
Collection defaultCollection() const
{
if ( !m_collection.isValid() )
m_collection = SpecialCollections::defaultCollection( sInvitationsType );
return m_collection;
}
void registerDefaultCollection()
{
defaultCollection();
registerCollection( sInvitationsType, m_collection );
}
SpecialCollectionsRequestJob* reguestJob() const
{
InvitationsCollectionRequestJob *job = new InvitationsCollectionRequestJob( const_cast<InvitationsCollection*>( this ),
m_agent );
job->requestDefaultCollection( sInvitationsType );
return job;
}
private:
InvitationsAgent *m_agent;
const QByteArray sInvitationsType;
mutable Collection m_collection;
};
InvitationsAgentItem::InvitationsAgentItem( InvitationsAgent *agent, const Item &originalItem )
: QObject( agent ), m_agent( agent ), m_originalItem( originalItem )
{
}
InvitationsAgentItem::~InvitationsAgentItem()
{
}
void InvitationsAgentItem::add( const Item &item )
{
kDebug();
const Collection collection = m_agent->collection();
Q_ASSERT( collection.isValid() );
ItemCreateJob *job = new ItemCreateJob( item, collection, this );
connect( job, SIGNAL(result(KJob*)), this, SLOT(createItemResult(KJob*)) );
m_jobs << job;
job->start();
}
void InvitationsAgentItem::createItemResult( KJob *job )
{
ItemCreateJob *createJob = qobject_cast<ItemCreateJob*>( job );
m_jobs.removeAll( createJob );
if ( createJob->error() ) {
kWarning() << "Failed to create new Item in invitations collection." << createJob->errorText();
return;
}
if ( !m_jobs.isEmpty() )
return;
ItemFetchJob *fetchJob = new ItemFetchJob( m_originalItem, this );
connect( fetchJob, SIGNAL(result(KJob*)), this, SLOT(fetchItemDone(KJob*)) );
fetchJob->start();
}
void InvitationsAgentItem::fetchItemDone( KJob *job )
{
if ( job->error() ) {
kWarning() << "Failed to fetch Item in invitations collection." << job->errorText();
return;
}
ItemFetchJob *fetchJob = qobject_cast<ItemFetchJob*>( job );
Q_ASSERT( fetchJob->items().count() == 1 );
Item modifiedItem = fetchJob->items().first();
Q_ASSERT( modifiedItem.isValid() );
modifiedItem.setFlag( Akonadi::MessageFlags::HasInvitation );
ItemModifyJob *modifyJob = new ItemModifyJob( modifiedItem, this );
connect( modifyJob, SIGNAL(result(KJob*)), this, SLOT(modifyItemDone(KJob*)) );
modifyJob->start();
}
void InvitationsAgentItem::modifyItemDone( KJob *job )
{
if ( job->error() ) {
kWarning() << "Failed to modify Item in invitations collection." << job->errorText();
return;
}
//ItemModifyJob *mj = qobject_cast<ItemModifyJob*>( job );
//kDebug()<<"Job successful done.";
}
InvitationsAgent::InvitationsAgent( const QString &id )
: AgentBase( id ), AgentBase::ObserverV2()
, m_invitationsCollection( new InvitationsCollection( this ) )
{
kDebug();
changeRecorder()->setChangeRecordingEnabled( false ); // behave like Monitor
changeRecorder()->itemFetchScope().fetchFullPayload();
changeRecorder()->setMimeTypeMonitored( QLatin1String("message/rfc822"), true );
//changeRecorder()->setCollectionMonitored( Collection::root(), true );
connect( this, SIGNAL(reloadConfiguration()), this, SLOT(initStart()) );
QTimer::singleShot( 0, this, SLOT(initStart()) );
}
InvitationsAgent::~InvitationsAgent()
{
delete m_invitationsCollection;
}
void InvitationsAgent::initStart()
{
kDebug();
m_invitationsCollection->clear();
if ( m_invitationsCollection->hasDefaultCollection() ) {
initDone();
} else {
SpecialCollectionsRequestJob *job = m_invitationsCollection->reguestJob();
connect( job, SIGNAL(result(KJob*)), this, SLOT(initDone(KJob*)) );
job->start();
}
/*
KConfig config( "akonadi_invitations_agent" );
KConfigGroup group = config.group( "General" );
m_resourceId = group.readEntry( "DefaultCalendarAgent", "default_ical_resource" );
newAgentCreated = false;
m_invitations = Akonadi::Collection();
AgentInstance resource = AgentManager::self()->instance( m_resourceId );
if ( resource.isValid() ) {
emit status( AgentBase::Running, i18n( "Reading..." ) );
QMetaObject::invokeMethod( this, "createAgentResult", Qt::QueuedConnection );
} else {
emit status( AgentBase::Running, i18n( "Creating..." ) );
AgentType type = AgentManager::self()->type( QLatin1String( "akonadi_ical_resource" ) );
AgentInstanceCreateJob *job = new AgentInstanceCreateJob( type, this );
connect( job, SIGNAL(result(KJob*)), this, SLOT(createAgentResult(KJob*)) );
job->start();
}
*/
}
void InvitationsAgent::initDone( KJob *job )
{
if ( job ) {
if ( job->error() ) {
kWarning() << "Failed to request default collection:" << job->errorText();
return;
}
m_invitationsCollection->registerDefaultCollection();
}
Q_ASSERT( m_invitationsCollection->defaultCollection().isValid() );
emit status( AgentBase::Idle, i18n( "Ready to dispatch invitations" ) );
}
Collection InvitationsAgent::collection()
{
return m_invitationsCollection->defaultCollection();
}
#if 0
KPIMIdentities::IdentityManager* InvitationsAgent::identityManager()
{
if ( !m_IdentityManager )
m_IdentityManager = new KPIMIdentities::IdentityManager( true /* readonly */, this );
return m_IdentityManager;
}
#endif
void InvitationsAgent::configure( WId windowId )
{
kDebug() << windowId;
/*
QWidget *parent = QWidget::find( windowId );
KDialog *dialog = new KDialog( parent );
QVBoxLayout *layout = new QVBoxLayout( dialog->mainWidget() );
//layout->addWidget( );
dialog->mainWidget()->setLayout( layout );
*/
initStart(); //reload
}
#if 0
void InvitationsAgent::createAgentResult( KJob *job )
{
kDebug();
AgentInstance agent;
if ( job ) {
if ( job->error() ) {
kWarning() << job->errorString();
emit status( AgentBase::Broken, i18n( "Failed to create resource: %1", job->errorString() ) );
return;
}
AgentInstanceCreateJob *j = static_cast<AgentInstanceCreateJob*>( job );
agent = j->instance();
agent.setName( i18n( "Invitations" ) );
m_resourceId = agent.identifier();
QDBusInterface conf( QString::fromLatin1( "org.freedesktop.Akonadi.Resource." ) + m_resourceId,
QString::fromLatin1( "/Settings" ),
QString::fromLatin1( "org.kde.Akonadi.ICal.Settings" ) );
QDBusReply<void> reply = conf.call( QString::fromLatin1( "setPath" ),
KGlobal::dirs()->localxdgdatadir() + "akonadi_ical_resource" );
if ( !reply.isValid() ) {
kWarning() << "dbus call failed, m_resourceId=" << m_resourceId;
emit status( AgentBase::Broken, i18n( "Failed to set the directory for invitations via D-Bus" ) );
AgentManager::self()->removeInstance( agent );
return;
}
KConfig config( "akonadi_invitations_agent" );
KConfigGroup group = config.group( "General" );
group.writeEntry( "DefaultCalendarAgent", m_resourceId );
newAgentCreated = true;
agent.reconfigure();
} else {
agent = AgentManager::self()->instance( m_resourceId );
Q_ASSERT( agent.isValid() );
}
ResourceSynchronizationJob *j = new ResourceSynchronizationJob( agent, this );
connect( j, SIGNAL(result(KJob*)), this, SLOT(resourceSyncResult(KJob*)) );
j->start();
}
void InvitationsAgent::resourceSyncResult( KJob *job )
{
kDebug();
if ( job->error() ) {
kWarning() << job->errorString();
emit status( AgentBase::Broken, i18n( "Failed to synchronize collection: %1", job->errorString() ) );
if ( newAgentCreated )
AgentManager::self()->removeInstance( AgentManager::self()->instance( m_resourceId ) );
return;
}
CollectionFetchJob *fjob = new CollectionFetchJob( Collection::root(), CollectionFetchJob::Recursive, this );
fjob->fetchScope().setContentMimeTypes( QStringList() << "text/calendar" );
fjob->fetchScope().setResource( m_resourceId );
connect( fjob, SIGNAL(result(KJob*)), this, SLOT(collectionFetchResult(KJob*)) );
fjob->start();
}
void InvitationsAgent::collectionFetchResult( KJob *job )
{
kDebug();
if ( job->error() ) {
kWarning() << job->errorString();
emit status( AgentBase::Broken, i18n( "Failed to fetch collection: %1", job->errorString() ) );
if ( newAgentCreated )
AgentManager::self()->removeInstance( AgentManager::self()->instance( m_resourceId ) );
return;
}
CollectionFetchJob *fj = static_cast<CollectionFetchJob *>( job );
if ( newAgentCreated ) {
// if the agent was just created then there is exactly one collection already
// and we just use that one.
Q_ASSERT( fj->collections().count() == 1 );
m_invitations = fj->collections().first();
initDone();
return;
}
KConfig config( "akonadi_invitations_agent" );
KConfigGroup group = config.group( "General" );
const QString collectionId = group.readEntry( "DefaultCalendarCollection", QString() );
if ( !collectionId.isEmpty() ) {
// look if the collection is still there. It may the case that there exists such
// a collection with the defined collectionId but that this is not a valid one
// and therefore not in the resultset.
const int id = collectionId.toInt();
foreach ( const Collection &c, fj->collections() ) {
if ( c.id() == id ) {
m_invitations = c;
initDone();
return;
}
}
}
// we need to create a new collection and use that one...
Collection c;
c.setName( "invitations" );
c.setParent( Collection::root() );
Q_ASSERT( !m_resourceId.isNull() );
c.setResource( m_resourceId );
c.setContentMimeTypes( QStringList()
<< "text/calendar"
<< "application/x-vnd.akonadi.calendar.event"
<< "application/x-vnd.akonadi.calendar.todo"
<< "application/x-vnd.akonadi.calendar.journal"
<< "application/x-vnd.akonadi.calendar.freebusy" );
CollectionCreateJob *cj = new CollectionCreateJob( c, this );
connect( cj, SIGNAL(result(KJob*)), this, SLOT(collectionCreateResult(KJob*)) );
cj->start();
}
void InvitationsAgent::collectionCreateResult( KJob *job )
{
kDebug();
if ( job->error() ) {
kWarning() << job->errorString();
emit status( AgentBase::Broken, i18n( "Failed to create collection: %1", job->errorString() ) );
if ( newAgentCreated )
AgentManager::self()->removeInstance( AgentManager::self()->instance( m_resourceId ) );
return;
}
CollectionCreateJob *j = static_cast<CollectionCreateJob*>( job );
m_invitations = j->collection();
initDone();
}
#endif
Item InvitationsAgent::handleContent( const QString &vcal,
const KCalCore::MemoryCalendar::Ptr &calendar,
const Item &item )
{
KCalCore::ICalFormat format;
KCalCore::ScheduleMessage::Ptr message = format.parseScheduleMessage( calendar, vcal );
if ( !message ) {
kWarning() << "Invalid invitation:" << vcal;
return Item();
}
kDebug() << "id=" << item.id() << "remoteId=" << item.remoteId() << "vcal=" << vcal;
KCalCore::Incidence::Ptr incidence = message->event().staticCast<KCalCore::Incidence>();
Q_ASSERT( incidence );
IncidenceAttribute *attr = new IncidenceAttribute;
attr->setStatus( QLatin1String("new") ); //TODO
//attr->setFrom( message->from()->asUnicodeString() );
attr->setReference( item.id() );
Item newItem;
newItem.setMimeType( incidence->mimeType() );
newItem.addAttribute( attr );
newItem.setPayload<KCalCore::Incidence::Ptr>( KCalCore::Incidence::Ptr( incidence->clone() ) );
return newItem;
}
void InvitationsAgent::itemAdded( const Item &item, const Collection &collection )
{
kDebug() << item.id() << collection;
Q_UNUSED( collection );
if ( !m_invitationsCollection->defaultCollection().isValid() ) {
kDebug() << "No default collection found";
return;
}
if ( collection.isVirtual() )
return;
if ( !item.hasPayload<KMime::Message::Ptr>() ) {
kDebug() << "Item has no payload";
return;
}
KMime::Message::Ptr message = item.payload<KMime::Message::Ptr>();
//TODO check if we are the sender and need to ignore the message...
//const QString sender = message->sender()->asUnicodeString();
//if ( identityManager()->thatIsMe( sender ) ) return;
KCalCore::MemoryCalendar::Ptr calendar( new KCalCore::MemoryCalendar( KSystemTimeZones::local() ) );
if ( message->contentType()->isMultipart() ) {
kDebug() << "message is multipart:" << message->attachments().size();
InvitationsAgentItem *it = 0;
foreach ( KMime::Content *content, message->contents() ) {
KMime::Headers::ContentType *ct = content->contentType();
Q_ASSERT( ct );
kDebug() << "Mimetype of the body part is " << ct->mimeType();
if ( ct->mimeType() != "text/calendar" )
continue;
Item newItem = handleContent( QLatin1String(content->body()), calendar, item );
if ( !newItem.hasPayload() ) {
kDebug() << "new item has no payload";
continue;
}
if ( !it )
it = new InvitationsAgentItem( this, item );
it->add( newItem );
}
} else {
kDebug() << "message is not multipart";
KMime::Headers::ContentType *ct = message->contentType();
Q_ASSERT( ct );
kDebug() << "Mimetype of the body is " << ct->mimeType();
if ( ct->mimeType() != "text/calendar" )
return;
kDebug() << "Message has an invitation in the body, processing";
Item newItem = handleContent( QLatin1String(message->body()), calendar, item );
if ( !newItem.hasPayload() ) {
kDebug() << "new item has no payload";
return;
}
InvitationsAgentItem *it = new InvitationsAgentItem( this, item );
it->add( newItem );
}
}
AKONADI_AGENT_MAIN( InvitationsAgent )

View file

@ -0,0 +1,97 @@
[Desktop Entry]
Name=Invitations Dispatcher Agent
Name[bs]=Agent za raspodjelu poziva
Name[ca]=Agent distribuïdor d'invitacions
Name[ca@valencia]=Agent distribuïdor d'invitacions
Name[cs]=Agent odesílatele pozvánek
Name[da]=Invitationsafsendingsagent
Name[de]=Agent zur Einladungs-Auslieferung
Name[el]=Πράκτορας αποστολής προσκλήσεων
Name[en_GB]=Invitations Dispatcher Agent
Name[es]=Agente despachador de invitaciones
Name[et]=Kutsete edastamise agent
Name[fi]=Kutsunlähetysagentti
Name[fr]=Agent de diffusions d'invitations
Name[gl]=Axente de Despacho de Convites
Name[hu]=Meghívófeladó ügynök
Name[ia]=Agente Distributor de Invitationes
Name[it]=Agente per la consegna degli inviti
Name[ja]=
Name[kk]=Шақыру реттеуш агенті
Name[km]=
Name[ko]=
Name[lt]=Laiškų gijų išdėstymo agentas
Name[lv]=Ielūgumu nosūtīšanas aģents
Name[nb]=Agent for invitasjonssendinger
Name[nds]=Inladenverdeel-Hölper
Name[nl]=Uitnodigingen-verspreidingsagent
Name[pl]=Agent wysyłania zaproszeń
Name[pt]=Agente de Despacho de Convites
Name[pt_BR]=Agente de encaminhamento de convites
Name[ro]=Agent de remitere a invitațiilor
Name[ru]=Агент диспетчера приглашений
Name[sk]=Agent spracovania pozvánok
Name[sl]=Posrednik za razpošiljanje povabil
Name[sr]=Агент отпремања позивница
Name[sr@ijekavian]=Агент отпремања позивница
Name[sr@ijekavianlatin]=Agent otpremanja pozivnica
Name[sr@latin]=Agent otpremanja pozivnica
Name[sv]=Modul för inbjudningssändning
Name[tr]=Davetiye Dağıtıcı Programı
Name[uk]=Агент розподілу запрошень
Name[x-test]=xxInvitations Dispatcher Agentxx
Name[zh_CN]=
Name[zh_TW]=
Comment=Dispatches invitations from your calendar
Comment[bs]=Raspoređuje pozive iz vašeg kalendara
Comment[ca]=Distribueix invitacions des del calendari
Comment[ca@valencia]=Distribueix invitacions des del calendari
Comment[da]=Udsender invitationer fra din kalender
Comment[de]=Verschickt Einladungen aus Ihren Kalender
Comment[el]=Διανέμει προσκλήσεις από το ημερολόγιό σας
Comment[en_GB]=Dispatches invitations from your calendar
Comment[es]=Remite invitaciones desde su calendario
Comment[et]=Kutsete edastamine sinu kalendrist
Comment[fi]=Lähettää kutsuja kalenteristasi
Comment[fr]=Diffuse les invitations à partir de votre agenda
Comment[gl]=Xestiona invitacións do calendario.
Comment[hu]=Meghívásokat kézbesít a naptárából
Comment[ia]=Expedi invitationes ex tu calendario
Comment[it]=Consegna inviti dal tuo calendario
Comment[kk]=Күнтізбеңіздегі шақыруларды үлестіру
Comment[ko]=
Comment[lt]=Išsiunčia pakvietimus iš Jūsų kalendoriaus
Comment[nb]=Sender ut invitasjoner fra din kalender
Comment[nds]=Verdeelt Inladen ut Dien Kalenner
Comment[nl]=Brengt uitnodigingen uit uw agenda naar elders
Comment[pl]=Rozsyła zaproszenia z twojego kalendarza
Comment[pt]=Trata dos convites do seu calendário
Comment[pt_BR]=Encaminhamento de convites do seu calendário
Comment[ro]=Remite invitații din calendar
Comment[ru]=Рассылает приглашения из календаря
Comment[sk]=Vybavuje pozvánky z vášho kalendára
Comment[sl]=Odpošlje povabila z vašega koledarja
Comment[sr]=Отпрема позивнице из вашег календара
Comment[sr@ijekavian]=Отпрема позивнице из вашег календара
Comment[sr@ijekavianlatin]=Otprema pozivnice iz vašeg kalendara
Comment[sr@latin]=Otprema pozivnice iz vašeg kalendara
Comment[sv]=Skickar inbjudningar från kalendern
Comment[tr]=Takviminizdeki davetleri yollar
Comment[uk]=Роповсюджує запрошення на основі даних календаря
Comment[x-test]=xxDispatches invitations from your calendarxx
Comment[zh_CN]=
Comment[zh_TW]=
Type=AkonadiAgent
Exec=akonadi_invitations_agent
Icon=mail-folder-outbox
X-Akonadi-Identifier=akonadi_invitations_agent
#X-Akonadi-Capabilities=Unique,Autostart,NoConfig
X-Akonadi-Capabilities=NoConfig
#X-Akonadi-MimeTypes=message/rfc822
#X-Akonadi-MimeTypes=text/calendar
X-Akonadi-MimeTypes=application/x-vnd.akonadi.calendar.event
#X-Akonadi-MimeTypes=application/x-vnd.akonadi.calendar.todo
#X-Akonadi-MimeTypes=application/x-vnd.akonadi.calendar.journal
#X-Akonadi-MimeTypes=application/x-vnd.akonadi.calendar.freebusy

View file

@ -0,0 +1,101 @@
/*
Copyright 2009 Sebastian Sauer <sebsauer@kdab.net>
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 INVITATIONSAGENT_H
#define INVITATIONSAGENT_H
#include <KCalCore/MemoryCalendar>
#include <Akonadi/AgentBase>
#include <Akonadi/Collection>
#include <Akonadi/Item>
#include <Akonadi/ItemCreateJob>
#include <QtCore/QObject>
class KJob;
class InvitationsAgent;
class InvitationsCollection;
class InvitationsAgentItem : public QObject
{
Q_OBJECT
public:
InvitationsAgentItem(InvitationsAgent *a, const Akonadi::Item &originalItem);
virtual ~InvitationsAgentItem();
void add(const Akonadi::Item &newItem);
private Q_SLOTS:
void createItemResult( KJob *job );
void fetchItemDone( KJob* );
void modifyItemDone( KJob *job );
private:
InvitationsAgent *m_agent;
const Akonadi::Item m_originalItem;
QList<Akonadi::ItemCreateJob*> m_jobs;
};
class InvitationsAgent : public Akonadi::AgentBase, public Akonadi::AgentBase::ObserverV2
{
Q_OBJECT
public:
explicit InvitationsAgent( const QString &id );
virtual ~InvitationsAgent();
Akonadi::Collection collection();
public Q_SLOTS:
virtual void configure( WId windowId );
private Q_SLOTS:
void initStart();
void initDone( KJob *job = 0 );
private:
Akonadi::Item handleContent( const QString &vcal,
const KCalCore::MemoryCalendar::Ptr &calendar,
const Akonadi::Item &item );
virtual void itemAdded( const Akonadi::Item &item, const Akonadi::Collection &collection );
/*
virtual void itemChanged( const Akonadi::Item &item, const QSet<QByteArray> &partIdentifiers );
virtual void itemRemoved( const Akonadi::Item &item );
virtual void collectionAdded( const Akonadi::Collection &collection, const Akonadi::Collection &parent );
virtual void collectionChanged( const Akonadi::Collection &collection );
virtual void collectionRemoved( const Akonadi::Collection &collection );
virtual void itemMoved( const Akonadi::Item &item, const Akonadi::Collection &collectionSource, const Akonadi::Collection &collectionDestination );
virtual void itemLinked( const Akonadi::Item &item, const Akonadi::Collection &collection );
virtual void itemUnlinked( const Akonadi::Item &item, const Akonadi::Collection &collection );
virtual void collectionMoved( const Akonadi::Collection &collection, const Akonadi::Collection &collectionSource, const Akonadi::Collection &collectionDestination );
virtual void collectionChanged( const Akonadi::Collection &collection, const QSet<QByteArray> &changedAttributes );
*/
private:
QString m_resourceId;
InvitationsCollection *m_invitationsCollection;
Akonadi::Collection m_collection;
};
#endif // MAILDISPATCHERAGENT_H

View file

@ -0,0 +1,41 @@
add_subdirectory( tests )
set( maildispatcheragent_SRCS
maildispatcheragent.cpp
outboxqueue.cpp
sendjob.cpp
sentactionhandler.cpp
storeresultjob.cpp
#configdialog.cpp
)
kde4_add_ui_files(maildispatcheragent_SRCS settings.ui)
kde4_add_kcfg_files(maildispatcheragent_SRCS settings.kcfgc)
kcfg_generate_dbus_interface(${CMAKE_CURRENT_SOURCE_DIR}/maildispatcheragent.kcfg org.kde.Akonadi.MailDispatcher.Settings)
qt4_add_dbus_adaptor(maildispatcheragent_SRCS
${CMAKE_CURRENT_BINARY_DIR}/org.kde.Akonadi.MailDispatcher.Settings.xml settings.h Settings
)
qt4_add_dbus_adaptor( maildispatcheragent_SRCS
org.freedesktop.Akonadi.MailDispatcherAgent.xml maildispatcheragent.h MailDispatcherAgent
)
if (RUNTIME_PLUGINS_STATIC)
add_definitions(-DMAIL_SERIALIZER_PLUGIN_STATIC)
endif ()
kdepim_add_agent(akonadi_maildispatcher_agent ${maildispatcheragent_SRCS})
if (RUNTIME_PLUGINS_STATIC)
target_link_libraries(akonadi_maildispatcher_agent akonadi_serializer_mail)
endif ()
if (Q_WS_MAC)
set_target_properties(akonadi_maildispatcher_agent PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/../Info.plist.template)
set_target_properties(akonadi_maildispatcher_agent PROPERTIES MACOSX_BUNDLE_GUI_IDENTIFIER "org.kde.Akonadi.maildispatcher")
set_target_properties(akonadi_maildispatcher_agent PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "KDE Akonadi Maildispatcher")
endif ()
target_link_libraries(akonadi_maildispatcher_agent ${KDEPIMLIBS_AKONADI_LIBS} ${KDEPIMLIBS_AKONADI_KMIME_LIBS} ${QT_QTCORE_LIBRARY} ${QT_QTDBUS_LIBRARY} ${KDE4_KDECORE_LIBS} ${KDE4_KIO_LIBS} ${KDEPIMLIBS_KMIME_LIBS} ${KDEPIMLIBS_MAILTRANSPORT_LIBS} ${KDE4_KNOTIFYCONFIG_LIBS})
install( FILES maildispatcheragent.desktop DESTINATION "${CMAKE_INSTALL_PREFIX}/share/akonadi/agents" )
install( FILES akonadi_maildispatcher_agent.notifyrc DESTINATION "${DATA_INSTALL_DIR}/akonadi_maildispatcher_agent" )

View file

@ -0,0 +1,4 @@
#! /bin/sh
$EXTRACTRC *.ui *.kcfg >> rc.cpp
$XGETTEXT *.cpp -o $podir/akonadi_maildispatcher_agent.pot
rm -f rc.cpp

View file

@ -0,0 +1,16 @@
* Once MoveJobs work, enable and test moving to sent-mail. Here is why it
doesn't work currently: Akonadi::Monitor sends itemMoved(...), but it is
not handled in AgentBase::Observer, and so it never gets "processed", and
is stuck in the Monitor/ChangeRecorder forever. (I.e. the resource will
not get any new notifications.) This has to be fixed in Akonadi, but that
means adding ObserverV2 or something.
* Figure out which / whether error strings should be i18n'd
* Should probably use progressMessage instead of statusMessage, but it seems
to be unimplemented in AgentInstance, and only a stub in AgentBase.
* Do something about timeouts.
* Test aborting and progress reporting for resource-based transports.
Bugs:
* Incorrect size reporting in itemChanged() from Monitor. Leads to displaying
>100% progress.
(found with: offline, queue some, online, abort, clearerror)

View file

@ -0,0 +1,194 @@
[Global]
IconName=mail-folder-outbox
Comment=KDE e-mail client
Comment[bg]=Пощенски клиент за KDE
Comment[bs]=KDE klijent elektronske pošte
Comment[ca]=Client de correu electrònic pel KDE
Comment[ca@valencia]=Client de correu electrònic pel KDE
Comment[cs]=Klient KDE pro čtení elektronické pošty
Comment[da]=KDE e-mail-klient
Comment[de]=E-Mail-Programm für KDE
Comment[el]=Πελάτης ηλ.ταχυδρομείου KDE
Comment[en_GB]=KDE e-mail client
Comment[es]=Cliente de correo de KDE
Comment[et]=KDE e-posti klient
Comment[fi]=KDE:n sähköpostiohjelma
Comment[fr]=Logiciel KDE de courrier électronique
Comment[ga]=Cliant Ríomhphoist KDE
Comment[gl]=Cliente de correo do KDE
Comment[hu]=KDE e-mail kliens
Comment[ia]=Programma KDE de e-posta
Comment[it]=Programma KDE di posta elettronica
Comment[ja]=KDE メールクライアント
Comment[kk]=KDE эл.пошта клиенті
Comment[km]=កម្មវិធី​អ៊ីមែល​របស់ KDE
Comment[ko]=KDE 이메일 클라이언트
Comment[lt]=KDE el. pašto klientas
Comment[lv]=KDE e-pasta klients
Comment[mr]=केडीई इ-मेल ग्राहक
Comment[nb]=KDE E-postklient
Comment[nds]=Nettpostprogramm för KDE
Comment[nl]=KDE e-mailclient
Comment[pa]=KDE ਈ-ਮੇਲ ਕਲਾਇਟ
Comment[pl]=Program pocztowy KDE
Comment[pt]=Cliente de e-mail do KDE
Comment[pt_BR]=Cliente de e-mail do KDE
Comment[ro]=Program de poștă electronică pentru KDE
Comment[ru]=Почтовый клиент KDE
Comment[sk]=KDE poštový klient
Comment[sl]=KDE-jev poštni odjemalec
Comment[sr]=КДЕ клијент е‑поште
Comment[sr@ijekavian]=КДЕ клијент е‑поште
Comment[sr@ijekavianlatin]=KDE klijent epošte
Comment[sr@latin]=KDE klijent epošte
Comment[sv]=KDE E-postklient
Comment[tr]=KDE e-posta istemcisi
Comment[uk]=Поштовий клієнт KDE
Comment[x-test]=xxKDE e-mail clientxx
Comment[zh_CN]=KDE 邮件客户端
Comment[zh_TW]=KDE 收發信軟體
Name=KDE Mail
Name[bg]=KDE поща
Name[bs]=KDE Mail
Name[ca]=Correu del KDE
Name[ca@valencia]=Correu del KDE
Name[cs]=Pošta v KDE
Name[da]=KDE Mail
Name[de]=KDE E-Mail
Name[el]=Αλληλογραφία KDE
Name[en_GB]=KDE Mail
Name[es]=Correo de KDE
Name[et]=KDE e-post
Name[fa]=نامه‌ی کی‌دی‌ای
Name[fi]=KDE Mail
Name[fr]=Messagerie KDE
Name[ga]=Ríomhphost KDE
Name[gl]=Correo do KDE
Name[hu]=KDE Mail
Name[ia]=Posta KDE
Name[it]=KDE Mail
Name[ja]=KDE Mail
Name[kk]=KDE поштасы
Name[km]=សំបុត្រ​របស់ KDE
Name[ko]=KDE 메일
Name[lt]=KDE paštas
Name[lv]=KDE pasts
Name[mr]=केडीई मेल
Name[nb]=KDE Mail
Name[nds]=KDE-Nettpost
Name[nl]=KDE E-mail
Name[pa]=KDE ਮੇਲ
Name[pl]=Poczta KDE
Name[pt]=Correio do KDE
Name[pt_BR]=E-mail do KDE
Name[ro]=Poșta KDE
Name[ru]=Почта KDE
Name[sk]=KDE Mail
Name[sl]=KDE-jeva pošta
Name[sr]=КДЕ пошта
Name[sr@ijekavian]=КДЕ пошта
Name[sr@ijekavianlatin]=KDE pošta
Name[sr@latin]=KDE pošta
Name[sv]=KDE:s e-postprogram
Name[tr]=KDE E-Posta
Name[uk]=Пошта KDE
Name[x-test]=xxKDE Mailxx
Name[zh_CN]=KDE 电子邮件
Name[zh_TW]=KDE 郵件軟體
[Event/emailsent]
Name=E-mail successfully sent
Name[bs]=E-mail uspješno poslan
Name[ca]=Correu electrònic enviat correctament
Name[ca@valencia]=Correu electrònic enviat correctament
Name[cs]=E-mail úspěšně odeslán
Name[da]=E-mail sendt
Name[de]=E-Mail erfolgreich gesendet
Name[el]=Η αλληλογραφία στάλθηκε με επιτυχία
Name[en_GB]=E-mail successfully sent
Name[es]=Correo enviado satisfactoriamente
Name[et]=E-kiri saadeti edukalt ära
Name[fa]=ای‌میل با موفقیت ارسال شد
Name[fi]=Sähköpostin lähetys onnistui
Name[fr]=Courrier électronique envoyé avec succès
Name[gl]=Enviouse a mensaxe sen problemas
Name[hu]=Az e-mail sikeresen elküldve
Name[ia]=E-posta inviate successosemente
Name[it]=Messaggio di posta inviato con successo
Name[kk]=Эл.пошта сәтті жіберілді
Name[km]=បាន​ផ្ញើ​អ៊ីមែល​ដោយ​ជោគជ័យ
Name[ko]=이메일을 성공적으로 전송함
Name[lt]=El. laiškas sėkmingai išsiųstas
Name[lv]=E-pasta veiksmīgi nosūtīts
Name[nb]=E.post vellykket sendt
Name[nds]=Nettbreef mit Spood loosstüert
Name[nl]=E-mailbericht met succes verzonden
Name[pa]=ਈਮੇਲ ਠੀਕ ਤਰ੍ਹਾਂ ਭੇਜੀ ਗਈ
Name[pl]=Poczta została wysłana pomyślnie
Name[pt]=O e-mail foi enviado com sucesso
Name[pt_BR]=E-mail enviado com sucesso
Name[ro]=Scrisoare expediată cu succes
Name[ru]=Почта успешно отправлена
Name[sk]=E-mail úspešne odoslaný
Name[sl]=E-pošta uspešno poslana
Name[sr]=Е‑пошта је успешно послата
Name[sr@ijekavian]=Е‑пошта је успешно послата
Name[sr@ijekavianlatin]=Epošta je uspešno poslata
Name[sr@latin]=Epošta je uspešno poslata
Name[sv]=E-post skickad med lyckat resultat
Name[tr]=E-posta başarıyla gönderildi
Name[ug]=ئېلخەت مۇۋەپپەقىيەتلىك يوللاندى
Name[uk]=Пошту успішно надіслано
Name[x-test]=xxE-mail successfully sentxx
Name[zh_CN]=邮件已成功发送
Name[zh_TW]=電子郵件已成功傳送
Action=Popup
IconName=mail-folder-outbox
[Event/sendingfailed]
Name=E-mail sending failed
Name[bs]=Slanje elektronske pošte neuspjelo
Name[ca]=Ha fallat en enviar el correu electrònic
Name[ca@valencia]=Ha fallat en enviar el correu electrònic
Name[cs]=Odesílání e-mailu selhalo
Name[da]=Afsendelse af e-mail mislykkedes
Name[de]=Fehler beim Versenden der E-Mail
Name[el]=Η αποστολή της αλληλογραφίας απέτυχε
Name[en_GB]=E-mail sending failed
Name[es]=Fallo en el envío del correo
Name[et]=E-kirja saatmine nurjus
Name[fa]=ارسال ای‌میل شکست خورد
Name[fi]=Sähköpostin lähetys epäonnistui
Name[fr]=Erreur lors de l'envoi du courrier électronique
Name[gl]=Produciuse un fallo ao enviar o correo
Name[hu]=Az e-mail küldése sikertelen
Name[ia]=Expedition de e-posta falleva
Name[it]=Invio del messaggio di posta non riuscito
Name[kk]=Эл.поштаны жолдау жаңылысы
Name[km]=បាន​បរាជ័យ​ក្នុង​ការ​ផ្ញើ​អ៊ីមែល
Name[ko]=이메일 전송 실패
Name[lt]=El. pašto siuntimas nepavyko
Name[lv]=E-pasta sūtīšana neizdevās
Name[nb]=E-postsending mislyktes
Name[nds]=Nettbreef lett sik nich loosstüern
Name[nl]=Verzenden van e-mail is mislukt
Name[pa]=ਈਮੇਲ ਭੇਜਣ ਲਈ ਫੇਲ੍ਹ
Name[pl]=Poczta nie została wysłana pomyślnie
Name[pt]=O envio do e-mail foi mal-sucedido
Name[pt_BR]=Falha no envio do e-mail
Name[ro]=Expedierea scrisorii a eșuat
Name[ru]=Не удалось отправить почту
Name[sk]=Poslanie správy zlyhalo
Name[sl]=Pošiljanje e-pošte ni uspelo
Name[sr]=Слање е‑поште није успело
Name[sr@ijekavian]=Слање е‑поште није успело
Name[sr@ijekavianlatin]=Slanje epošte nije uspelo
Name[sr@latin]=Slanje epošte nije uspelo
Name[sv]=Misslyckades skicka brev
Name[tr]=E-posta gönderimi başarısız oldu
Name[uk]=Спроба надсилання повідомлення зазнала невдачі
Name[x-test]=xxE-mail sending failedxx
Name[zh_CN]=发送邮件失败
Name[zh_TW]=傳送信件失敗
Action=Popup
IconName=mail-mark-junk

View file

@ -0,0 +1,80 @@
/*
Copyright 2008 Ingo Klöcker <kloecker@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 "configdialog.h"
#include "settings.h"
#include <Akonadi/Collection>
#include <Akonadi/CollectionFetchJob>
#include <Akonadi/CollectionRequester>
#include <KConfigDialogManager>
#include <KMime/Message>
using namespace Akonadi;
ConfigDialog::ConfigDialog( QWidget *parent )
: KDialog( parent )
{
mUi.setupUi( mainWidget() );
mManager = new KConfigDialogManager( this, Settings::self() );
mManager->updateWidgets();
ui.outboxSelector->setMimeTypeFilter( QStringList() << KMime::Message::mimeType() );
// collection has no name if I skip the fetch job and just do Collection c(id)
CollectionFetchJob *job = new CollectionFetchJob( Collection( Settings::self()->outbox() ), CollectionFetchJob::Base );
if ( job->exec() ) {
const Collection::List collections = job->collections();
if ( !collections.isEmpty() )
ui.outboxSelector->setCollection( collections.first() );
}
ui.sentMailSelector->setMimeTypeFilter( QStringList() << KMime::Message::mimeType() );
job = new CollectionFetchJob( Collection( Settings::self()->sentMail() ), CollectionFetchJob::Base );
if ( job->exec() ) {
const Collection::List collections = job->collections();
if ( !collections.isEmpty() )
ui.sentMailSelector->setCollection( collections.first() );
}
connect( this, SIGNAL(okClicked()), this, SLOT(save()) );
}
void ConfigDialog::save()
{
mManager->updateSettings();
const Collection outbox = ui.outboxSelector->collection();
if ( outbox.isValid() ) {
kDebug() << "Collection" << outbox.id() << "selected for outbox.";
Settings::self()->setOutbox( outbox.id() );
}
const Collection sentMail = ui.sentMailSelector->collection();
if ( sentMail.isValid() ) {
kDebug() << "Collection" << sentMail.id() << "selected for sentMail.";
Settings::self()->setSentMail( sentMail.id() );
}
Settings::self()->writeConfig();
}

View file

@ -0,0 +1,44 @@
/*
Copyright 2008 Ingo Klöcker <kloecker@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 CONFIGDIALOG_H
#define CONFIGDIALOG_H
#include <KDialog>
#include "ui_settings.h"
class KConfigDialogManager;
class ConfigDialog : public KDialog
{
Q_OBJECT
public:
explicit ConfigDialog( QWidget *parent = 0 );
private Q_SLOTS:
void save();
private:
Ui::ConfigDialog mUi;
KConfigDialogManager *mManager;
};
#endif

View file

@ -0,0 +1,373 @@
/*
Copyright 2008 Ingo Klöcker <kloecker@kde.org>
Copyright 2009 Constantin Berzan <exit3219@gmail.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 "maildispatcheragent.h"
//#include "configdialog.h"
#include "maildispatcheragentadaptor.h"
#include "outboxqueue.h"
#include "sendjob.h"
#include "sentactionhandler.h"
#include "settings.h"
#include "settingsadaptor.h"
#include <akonadi/agentfactory.h>
#include <akonadi/dbusconnectionpool.h>
#include <akonadi/itemfetchscope.h>
#include <mailtransport/sentactionattribute.h>
#include <knotifyconfigwidget.h>
#include <KDebug>
#include <KIcon>
#include <KIconLoader>
#include <KLocalizedString>
#include <KLocalizedString>
#include <KMime/Message>
#include <KNotification>
#include <KWindowSystem>
#include <KLocale>
#include <QtCore/QTimer>
#include <QtDBus/QDBusConnection>
#ifdef KDEPIM_STATIC_LIBS
extern bool ___MailTransport____INIT();
#endif
#ifdef MAIL_SERIALIZER_PLUGIN_STATIC
#include <QtPlugin>
Q_IMPORT_PLUGIN(akonadi_serializer_mail)
#endif
using namespace Akonadi;
class MailDispatcherAgent::Private
{
public:
Private( MailDispatcherAgent *parent )
: q( parent ),
queue( 0 ),
currentJob( 0 ),
aborting( false ),
sendingInProgress( false ),
sentAnything( false ),
errorOccurred( false ),
sentItemsSize( 0 ),
sentActionHandler( 0 )
{
}
~Private()
{
}
MailDispatcherAgent * const q;
OutboxQueue *queue;
SendJob *currentJob;
Item currentItem;
bool aborting;
bool sendingInProgress;
bool sentAnything;
bool errorOccurred;
qulonglong sentItemsSize;
SentActionHandler *sentActionHandler;
// slots:
void abort();
void dispatch();
void itemFetched( const Item &item );
void queueError( const QString &message );
void sendPercent( KJob *job, unsigned long percent );
void sendResult( KJob *job );
void emitStatusReady();
};
void MailDispatcherAgent::Private::abort()
{
if ( !q->isOnline() ) {
kDebug() << "Offline. Ignoring call.";
return;
}
if ( aborting ) {
kDebug() << "Already aborting.";
return;
}
if ( !sendingInProgress && queue->isEmpty() ) {
kDebug() << "MDA is idle.";
Q_ASSERT( q->status() == AgentBase::Idle );
} else {
kDebug() << "Aborting...";
aborting = true;
if ( currentJob ) {
currentJob->abort();
}
// Further SendJobs will mark remaining items in the queue as 'aborted'.
}
}
void MailDispatcherAgent::Private::dispatch()
{
Q_ASSERT( queue );
if ( !q->isOnline() || sendingInProgress ) {
kDebug() << "Offline or busy. See you later.";
return;
}
if ( !queue->isEmpty() ) {
if ( !sentAnything ) {
sentAnything = true;
sentItemsSize = 0;
emit q->percent( 0 );
}
emit q->status( AgentBase::Running,
i18np( "Sending messages (1 item in queue)...",
"Sending messages (%1 items in queue)...", queue->count() ) );
kDebug() << "Attempting to dispatch the next message.";
sendingInProgress = true;
queue->fetchOne(); // will trigger itemFetched
} else {
kDebug() << "Empty queue.";
if ( aborting ) {
// Finished marking messages as 'aborted'.
aborting = false;
sentAnything = false;
emit q->status( AgentBase::Idle, i18n( "Sending canceled." ) );
QTimer::singleShot( 3000, q, SLOT(emitStatusReady()) );
} else {
if ( sentAnything ) {
// Finished sending messages in queue.
sentAnything = false;
emit q->percent( 100 );
emit q->status( AgentBase::Idle, i18n( "Finished sending messages." ) );
if ( !errorOccurred ) {
KNotification *notify = new KNotification( QLatin1String("emailsent") );
notify->setComponentData( q->componentData() );
notify->setTitle( i18nc( "Notification title when email was sent", "E-Mail Successfully Sent" ) );
notify->setText( i18nc( "Notification when the email was sent", "Your E-Mail has been sent successfully." ) );
notify->sendEvent();
}
} else {
// Empty queue.
emit q->status( AgentBase::Idle, i18n( "No items in queue." ) );
}
QTimer::singleShot( 3000, q, SLOT(emitStatusReady()) );
}
errorOccurred = false;
}
}
MailDispatcherAgent::MailDispatcherAgent( const QString &id )
: AgentBase( id ),
d( new Private( this ) )
{
kDebug() << "maildispatcheragent: At your service, sir!";
#ifdef KDEPIM_STATIC_LIBS
___MailTransport____INIT();
#endif
KGlobal::locale()->insertCatalog( QLatin1String("libakonadi-kmime") ); // for special collection translation
new SettingsAdaptor( Settings::self() );
new MailDispatcherAgentAdaptor( this );
DBusConnectionPool::threadConnection().registerObject( QLatin1String( "/Settings" ),
Settings::self(), QDBusConnection::ExportAdaptors );
DBusConnectionPool::threadConnection().registerObject( QLatin1String( "/MailDispatcherAgent" ),
this, QDBusConnection::ExportAdaptors );
DBusConnectionPool::threadConnection().registerService( QLatin1String( "org.freedesktop.Akonadi.MailDispatcherAgent" ) );
d->queue = new OutboxQueue( this );
connect( d->queue, SIGNAL(newItems()),
this, SLOT(dispatch()) );
connect( d->queue, SIGNAL(itemReady(Akonadi::Item)),
this, SLOT(itemFetched(Akonadi::Item)) );
connect( d->queue, SIGNAL(error(QString)),
this, SLOT(queueError(QString)) );
connect( this, SIGNAL(itemProcessed(Akonadi::Item,bool)),
d->queue, SLOT(itemProcessed(Akonadi::Item,bool)) );
connect( this, SIGNAL(abortRequested()),
this, SLOT(abort()) );
d->sentActionHandler = new SentActionHandler( this );
setNeedsNetwork( true );
}
MailDispatcherAgent::~MailDispatcherAgent()
{
delete d;
}
void MailDispatcherAgent::configure( WId windowId )
{
Q_UNUSED( windowId );
KNotifyConfigWidget::configure( 0 );
}
void MailDispatcherAgent::doSetOnline( bool online )
{
Q_ASSERT( d->queue );
if ( online ) {
kDebug() << "Online. Dispatching messages.";
emit status( AgentBase::Idle, i18n( "Online, sending messages in queue." ) );
QTimer::singleShot( 0, this, SLOT(dispatch()) );
} else {
kDebug() << "Offline.";
emit status( AgentBase::Idle, i18n( "Offline, message sending suspended." ) );
// TODO: This way, the OutboxQueue will continue to react to changes in
// the outbox, but the MDA will just not send anything. Is this what we
// want?
}
AgentBase::doSetOnline( online );
}
void MailDispatcherAgent::Private::itemFetched( const Item &item )
{
kDebug() << "Fetched item" << item.id() << "; creating SendJob.";
Q_ASSERT( sendingInProgress );
Q_ASSERT( !currentItem.isValid() );
currentItem = item;
Q_ASSERT( currentJob == 0 );
emit q->itemDispatchStarted();
currentJob = new SendJob( item, q );
if ( aborting ) {
currentJob->setMarkAborted();
}
q->status( AgentBase::Running, i18nc( "Message with given subject is being sent.", "Sending: %1",
item.payload<KMime::Message::Ptr>()->subject()->asUnicodeString() ) );
connect( currentJob, SIGNAL(result(KJob*)),
q, SLOT(sendResult(KJob*)) );
connect( currentJob, SIGNAL(percent(KJob*,ulong)),
q, SLOT(sendPercent(KJob*,ulong)) );
currentJob->start();
}
void MailDispatcherAgent::Private::queueError( const QString &message )
{
emit q->error( message );
errorOccurred = true;
// FIXME figure out why this does not set the status to Broken, etc.
}
void MailDispatcherAgent::Private::sendPercent( KJob *job, unsigned long )
{
Q_ASSERT( sendingInProgress );
Q_ASSERT( job == currentJob );
// The progress here is actually the TransportJob, not the entire SendJob,
// because the post-job doesn't report progress. This should be fine,
// since the TransportJob is the lengthiest operation.
// Give the transport 80% of the weight, and move-to-sendmail 20%.
const double transportWeight = 0.8;
const int percent = 100 * ( sentItemsSize + job->processedAmount( KJob::Bytes ) * transportWeight )
/ ( sentItemsSize + currentItem.size() + queue->totalSize() );
kDebug() << "sentItemsSize" << sentItemsSize
<< "this job processed" << job->processedAmount( KJob::Bytes )
<< "queue totalSize" << queue->totalSize()
<< "total total size (sent+current+queue)" << ( sentItemsSize + currentItem.size() + queue->totalSize() )
<< "new percentage" << percent << "old percentage" << q->progress();
if ( percent != q->progress() ) {
// The progress can decrease too, if messages got added to the queue.
emit q->percent( percent );
}
// It is possible that the number of queued messages has changed.
emit q->status( AgentBase::Running,
i18np( "Sending messages (1 item in queue)...",
"Sending messages (%1 items in queue)...", 1 + queue->count() ) );
}
void MailDispatcherAgent::Private::sendResult( KJob *job )
{
Q_ASSERT( sendingInProgress );
Q_ASSERT( job == currentJob );
currentJob->disconnect( q );
currentJob = 0;
Q_ASSERT( currentItem.isValid() );
sentItemsSize += currentItem.size();
emit q->itemProcessed( currentItem, !job->error() );
const Akonadi::Item sentItem = currentItem;
currentItem = Item();
if ( job->error() ) {
// The SendJob gave the item an ErrorAttribute, so we don't have to
// do anything.
kDebug() << "Sending failed. error:" << job->errorString();
KNotification *notify = new KNotification( QLatin1String("sendingfailed") );
notify->setComponentData( q->componentData() );
notify->setTitle( i18nc( "Notification title when email sending failed", "E-Mail Sending Failed" ) );
notify->setText( job->errorString() );
notify->sendEvent();
errorOccurred = true;
} else {
kDebug() << "Sending succeeded.";
// handle possible sent actions
const MailTransport::SentActionAttribute *attribute = sentItem.attribute<MailTransport::SentActionAttribute>();
if ( attribute ) {
foreach ( const MailTransport::SentActionAttribute::Action &action, attribute->actions() )
sentActionHandler->runAction( action );
}
}
// dispatch next message
sendingInProgress = false;
QTimer::singleShot( 0, q, SLOT(dispatch()) );
}
void MailDispatcherAgent::Private::emitStatusReady()
{
if ( q->status() == AgentBase::Idle ) {
// If still idle after aborting, clear 'aborted' status.
emit q->status( AgentBase::Idle, i18n( "Ready to dispatch messages." ) );
}
}
#ifdef KDEPIM_PLUGIN_AGENT
AKONADI_AGENT_FACTORY( MailDispatcherAgent, akonadi_maildispatcher_agent )
#else
AKONADI_AGENT_MAIN( MailDispatcherAgent )
#endif
#include "moc_maildispatcheragent.cpp"

View file

@ -0,0 +1,93 @@
[Desktop Entry]
Name=Mail Dispatcher Agent
Name[bs]=Dispačer mail agent
Name[ca]=Agent distribuïdor de correu
Name[ca@valencia]=Agent distribuïdor de correu
Name[cs]=Agent odesílatele zpráv
Name[da]=Mailafsendingsagent (MDA)
Name[de]=Agent zur Nachrichten-Auslieferung
Name[el]=Πράκτορας αποστολής αλληλογραφίας
Name[en_GB]=Mail Dispatcher Agent
Name[es]=Agente despachador de correo
Name[et]=Kirjade edastamise agent
Name[fi]=Postinvälitysagentti
Name[fr]=Agent de diffusion de messages
Name[gl]=Axente de Despacho de Correo
Name[hu]=Levélfeladó ügynök
Name[ia]=Agente Distributor de Posta
Name[it]=Agente per la consegna della posta
Name[ja]=
Name[kk]=Пошта реттеуш агенті
Name[km]=
Name[ko]=
Name[lt]=Laiškų gijų išdėstymo agentas
Name[lv]=Pasta nosūtīšanas aģents
Name[nb]=Agent for e-postsending
Name[nds]=Nettpostverdeel-Hölper
Name[nl]=Agent voor het verzenden van e-mail
Name[pa]= ਿ
Name[pl]=Agent przyjmowania poczty
Name[pt]=Agente de Despacho do Correio
Name[pt_BR]=Agente de encaminhamento de e-mails
Name[ro]=Agent de livrare a mesajelor
Name[ru]=Агент почтового диспетчера
Name[sk]=Agent spracovania pošty
Name[sl]=Posrednik za razpošiljanje pošte
Name[sr]=Агент отпремања поште
Name[sr@ijekavian]=Агент отпремања поште
Name[sr@ijekavianlatin]=Agent otpremanja pošte
Name[sr@latin]=Agent otpremanja pošte
Name[sv]=E-postsändningsmodul
Name[tr]=E-posta Yönetim Aracı
Name[ug]=Mail Dispatcher Agent
Name[uk]=Агент розподілу пошти
Name[x-test]=xxMail Dispatcher Agentxx
Name[zh_CN]=
Name[zh_TW]=
Comment=Dispatches email messages
Comment[bs]=Raspoređuje E-mail poruke
Comment[ca]=Distribueix missatges de correu electrònic
Comment[ca@valencia]=Distribueix missatges de correu electrònic
Comment[cs]=Odesílá e-mailové zprávy
Comment[da]=Udsender e-mails
Comment[de]=Verteilt E-Mail-Nachrichten
Comment[el]=Διανέμει μηνύματα ηλ. ταχυδρομείου
Comment[en_GB]=Dispatches email messages
Comment[es]=Remite mensajes de correo
Comment[et]=Kirjade edastamine
Comment[fi]=Lähettää sähköpostiviestejä
Comment[fr]=Diffuse les courriers électroniques
Comment[gl]=Xestiona mensaxes de correo.
Comment[hu]=E-mail üzeneteket kézbesít
Comment[ia]=Expedi messages de e-posta
Comment[it]=Invia messaggi di posta elettronica
Comment[kk]=Пошта хаттарын үлестіру
Comment[ko]=
Comment[lt]=Išsiunčia el. laiškus
Comment[nb]=Sender ut e-postmeldinger
Comment[nds]=Verdeelt Nettpost
Comment[nl]=Verstuurt e-mailberichten
Comment[pl]=Rozsyła wiadomości e-mail
Comment[pt]=Trata das mensagens de e-mail
Comment[pt_BR]=Encaminhamento de e-mails
Comment[ro]=Remite scrisori electronice
Comment[ru]=Рассылает почтовые сообщения
Comment[sk]=Vybavuje e-mailové správy
Comment[sl]=Odpošlje e-poštna sporočila
Comment[sr]=Отпрема епоштанске поруке
Comment[sr@ijekavian]=Отпрема епоштанске поруке
Comment[sr@ijekavianlatin]=Otprema epoštanske poruke
Comment[sr@latin]=Otprema epoštanske poruke
Comment[sv]=Skickar brev med e-post
Comment[tr]=E-posta mesajlarını yollar
Comment[uk]=Розповсюджує повідомлення електронної пошти
Comment[x-test]=xxDispatches email messagesxx
Comment[zh_CN]=
Comment[zh_TW]=
Type=AkonadiAgent
Exec=akonadi_maildispatcher_agent
Icon=mail-folder-outbox
X-Akonadi-MimeTypes=message/rfc822
X-Akonadi-Capabilities=Unique,Autostart
X-Akonadi-Identifier=akonadi_maildispatcher_agent

View file

@ -0,0 +1,75 @@
/*
Copyright 2008 Ingo Klöcker <kloecker@kde.org>
Copyright 2009 Constantin Berzan <exit3219@gmail.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 MAILDISPATCHERAGENT_H
#define MAILDISPATCHERAGENT_H
#include <Akonadi/AgentBase>
namespace Akonadi {
class Item;
}
/**
* @short This agent dispatches mail put into the outbox collection.
*/
class MailDispatcherAgent : public Akonadi::AgentBase
{
Q_OBJECT
Q_CLASSINFO( "D-Bus Interface", "org.freedesktop.Akonadi.MailDispatcherAgent" )
public:
explicit MailDispatcherAgent( const QString &id );
~MailDispatcherAgent();
public Q_SLOTS:
virtual void configure( WId windowId );
Q_SIGNALS:
/**
* Emitted when the MDA has attempted to send an item.
*/
void itemProcessed( const Akonadi::Item &item, bool result );
/**
* Emitted when the MDA has begun processing an item
*/
Q_SCRIPTABLE void itemDispatchStarted();
protected:
virtual void doSetOnline( bool online );
private:
//@cond PRIVATE
class Private;
Private* const d;
Q_PRIVATE_SLOT( d, void abort() )
Q_PRIVATE_SLOT( d, void dispatch() )
Q_PRIVATE_SLOT( d, void itemFetched( const Akonadi::Item& ) )
Q_PRIVATE_SLOT( d, void queueError( const QString& ) )
Q_PRIVATE_SLOT( d, void sendPercent( KJob*, unsigned long ) )
Q_PRIVATE_SLOT( d, void sendResult( KJob* ) )
Q_PRIVATE_SLOT( d, void emitStatusReady() )
//@endcond
};
#endif // MAILDISPATCHERAGENT_H

View file

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
xmlns:kcfg="http://www.kde.org/standards/kcfg/1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
<kcfgfile name="maildispatcheragentrc"/>
<group name="General">
<entry name="Outbox" type="LongLong">
<label>Outbox collection id</label>
<default>-1</default>
</entry>
<entry name="SentMail" type="LongLong">
<label>Sent Mail collection id</label>
<default>-1</default>
</entry>
</group>
</kcfg>

View file

@ -0,0 +1,7 @@
<!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.MailDispatcherAgent">
<signal name="itemDispatchStarted">
</signal>
</interface>
</node>

View file

@ -0,0 +1,459 @@
/*
Copyright (c) 2009 Constantin Berzan <exit3219@gmail.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 "outboxqueue.h"
#include <QMultiMap>
#include <QSet>
#include <QTimer>
#include <KDebug>
#include <KLocalizedString>
#include <Akonadi/Attribute>
#include <Akonadi/Item>
#include <Akonadi/ItemFetchJob>
#include <Akonadi/ItemFetchScope>
#include <Akonadi/Monitor>
#include <akonadi/kmime/addressattribute.h>
#include <akonadi/kmime/messageflags.h>
#include <akonadi/kmime/specialmailcollections.h>
#include <akonadi/kmime/specialmailcollectionsrequestjob.h>
#include <kmime/kmime_message.h>
#include <boost/shared_ptr.hpp>
#include <mailtransport/dispatchmodeattribute.h>
#include <mailtransport/sentbehaviourattribute.h>
#include <mailtransport/transportattribute.h>
using namespace Akonadi;
using namespace MailTransport;
static const int OUTBOX_DISCOVERY_RETRIES = 3; // number of times we try to find or create the outbox
static const int OUTBOX_DISCOVERY_WAIT_TIME = 5000; // number of ms to wait before retrying
/**
* @internal
*/
class OutboxQueue::Private
{
public:
Private( OutboxQueue *qq )
: q( qq ),
outbox( -1 ),
monitor( 0 ),
futureTimer( 0 ),
totalSize( 0 ),
outboxDiscoveryRetries( 0 )
{
}
OutboxQueue *const q;
Collection outbox;
Monitor *monitor;
QList<Item> queue;
QSet<Item> futureItems; // keeps track of items removed in the meantime
QMultiMap<QDateTime, Item> futureMap;
QTimer *futureTimer;
qulonglong totalSize;
int outboxDiscoveryRetries;
#if 0
// If an item is modified externally between the moment we pass it to
// the MDA and the time the MDA marks it as sent, then we will get
// itemChanged() and may mistakenly re-add the item to the queue.
// So we ignore the item that we pass to the MDA, until the MDA finishes
// sending it.
Item currentItem;
#endif
// HACK: The above is not enough.
// Apparently change notifications are delayed sometimes (???)
// and we re-add an item long after it was sent. So keep a list of sent
// items.
// TODO debug and figure out why this happens.
QSet<Item::Id> ignore;
void initQueue();
void addIfComplete( const Item &item );
// slots:
void checkFuture();
void collectionFetched( KJob *job );
void itemFetched( KJob *job );
void localFoldersChanged();
void localFoldersRequestResult( KJob *job );
void itemAdded( const Item &item );
void itemChanged( const Item &item );
void itemMoved( const Item &item, const Collection &source, const Collection &dest );
void itemRemoved( const Item &item );
void itemProcessed( const Item &item, bool result );
};
void OutboxQueue::Private::initQueue()
{
totalSize = 0;
queue.clear();
kDebug() << "Fetching items in collection" << outbox.id();
ItemFetchJob *job = new ItemFetchJob( outbox );
job->fetchScope().fetchAllAttributes();
job->fetchScope().fetchFullPayload( false );
connect( job, SIGNAL(result(KJob*)), q, SLOT(collectionFetched(KJob*)) );
}
void OutboxQueue::Private::addIfComplete( const Item &item )
{
if ( ignore.contains( item.id() ) ) {
kDebug() << "Item" << item.id() << "is ignored.";
return;
}
if ( queue.contains( item ) ) {
kDebug() << "Item" << item.id() << "already in queue!";
return;
}
if ( !item.hasAttribute<AddressAttribute>() ) {
kWarning() << "Item" << item.id() << "does not have the required attribute Address.";
return;
}
if ( !item.hasAttribute<DispatchModeAttribute>() ) {
kWarning() << "Item" << item.id() << "does not have the required attribute DispatchMode.";
return;
}
if ( !item.hasAttribute<SentBehaviourAttribute>() ) {
kWarning() << "Item" << item.id() << "does not have the required attribute SentBehaviour.";
return;
}
if ( !item.hasAttribute<TransportAttribute>() ) {
kWarning() << "Item" << item.id() << "does not have the required attribute Transport.";
return;
}
if ( !item.hasFlag( Akonadi::MessageFlags::Queued ) ) {
kDebug() << "Item" << item.id() << "has no '$QUEUED' flag.";
return;
}
const DispatchModeAttribute *dispatchModeAttribute = item.attribute<DispatchModeAttribute>();
Q_ASSERT( dispatchModeAttribute );
if ( dispatchModeAttribute->dispatchMode() == DispatchModeAttribute::Manual ) {
kDebug() << "Item" << item.id() << "is queued to be sent manually.";
return;
}
const TransportAttribute *transportAttribute = item.attribute<TransportAttribute>();
Q_ASSERT( transportAttribute );
if ( transportAttribute->transport() == 0 ) {
kWarning() << "Item" << item.id() << "has invalid transport.";
return;
}
const SentBehaviourAttribute *sentBehaviourAttribute = item.attribute<SentBehaviourAttribute>();
Q_ASSERT( sentBehaviourAttribute );
if ( sentBehaviourAttribute->sentBehaviour() == SentBehaviourAttribute::MoveToCollection &&
!sentBehaviourAttribute->moveToCollection().isValid() ) {
kWarning() << "Item" << item.id() << "has invalid sent-mail collection.";
return;
}
// This check requires fetchFullPayload. -> slow (?)
/*
if ( !item.hasPayload<KMime::Message::Ptr>() ) {
kWarning() << "Item" << item.id() << "does not have KMime::Message::Ptr payload.";
return;
}
*/
if ( dispatchModeAttribute->dispatchMode() == DispatchModeAttribute::Automatic &&
dispatchModeAttribute->sendAfter().isValid() &&
dispatchModeAttribute->sendAfter() > QDateTime::currentDateTime() ) {
// All the above was OK, so accept it for the future.
kDebug() << "Item" << item.id() << "is accepted to be sent in the future.";
futureMap.insert( dispatchModeAttribute->sendAfter(), item );
Q_ASSERT( !futureItems.contains( item ) );
futureItems.insert( item );
checkFuture();
return;
}
kDebug() << "Item" << item.id() << "is accepted into the queue (size" << item.size() << ").";
Q_ASSERT( !queue.contains( item ) );
totalSize += item.size();
queue.append( item );
emit q->newItems();
}
void OutboxQueue::Private::checkFuture()
{
kDebug() << "The future is here." << futureMap.count() << "items in futureMap.";
Q_ASSERT( futureTimer );
futureTimer->stop();
// By default, re-check in one hour.
futureTimer->setInterval( 60 * 60 * 1000 );
// Check items in ascending order of date.
while ( !futureMap.isEmpty() ) {
QMap<QDateTime, Item>::iterator it = futureMap.begin();
kDebug() << "Item with due date" << it.key();
if ( it.key() > QDateTime::currentDateTime() ) {
const int secs = QDateTime::currentDateTime().secsTo( it.key() ) + 1;
kDebug() << "Future, in" << secs << "seconds.";
Q_ASSERT( secs >= 0 );
if ( secs < 60 * 60 ) {
futureTimer->setInterval( secs * 1000 );
}
break; // all others are in the future too
}
if ( !futureItems.contains( it.value() ) ) {
kDebug() << "Item disappeared.";
} else {
kDebug() << "Due date is here. Queuing.";
addIfComplete( it.value() );
futureItems.remove( it.value() );
}
futureMap.erase( it );
}
kDebug() << "Timer set to checkFuture again in" << futureTimer->interval() / 1000 << "seconds"
<< "(that is" << futureTimer->interval() / 1000 / 60 << "minutes).";
futureTimer->start();
}
void OutboxQueue::Private::collectionFetched( KJob *job )
{
if ( job->error() ) {
kWarning() << "Failed to fetch outbox collection. Queue will be empty until the outbox changes.";
return;
}
const ItemFetchJob *fetchJob = qobject_cast<ItemFetchJob*>( job );
Q_ASSERT( fetchJob );
kDebug() << "Fetched" << fetchJob->items().count() << "items.";
foreach ( const Item &item, fetchJob->items() ) {
addIfComplete( item );
}
}
void OutboxQueue::Private::itemFetched( KJob *job )
{
if ( job->error() ) {
kDebug() << "Error fetching item:" << job->errorString() << ". Trying next item in queue.";
q->fetchOne();
}
const ItemFetchJob *fetchJob = qobject_cast<ItemFetchJob*>( job );
Q_ASSERT( fetchJob );
if ( fetchJob->items().count() != 1 ) {
kDebug() << "Fetched" << fetchJob->items().count() << ", expected 1. Trying next item in queue.";
q->fetchOne();
}
if ( !fetchJob->items().isEmpty() ) {
emit q->itemReady( fetchJob->items().first() );
}
}
void OutboxQueue::Private::localFoldersChanged()
{
// Called on startup, and whenever the local folders change.
if ( SpecialMailCollections::self()->hasDefaultCollection( SpecialMailCollections::Outbox ) ) {
// Outbox is ready, init the queue from it.
const Collection collection = SpecialMailCollections::self()->defaultCollection( SpecialMailCollections::Outbox );
Q_ASSERT( collection.isValid() );
if ( outbox != collection ) {
monitor->setCollectionMonitored( outbox, false );
monitor->setCollectionMonitored( collection, true );
outbox = collection;
kDebug() << "Changed outbox to" << outbox.id();
initQueue();
}
} else {
// Outbox is not ready. Request it, since otherwise we will not know when
// new messages appear.
// (Note that we are a separate process, so we get no notification when
// MessageQueueJob requests the Outbox.)
monitor->setCollectionMonitored( outbox, false );
outbox = Collection( -1 );
SpecialMailCollectionsRequestJob *job = new SpecialMailCollectionsRequestJob( q );
job->requestDefaultCollection( SpecialMailCollections::Outbox );
connect( job, SIGNAL(result(KJob*)), q, SLOT(localFoldersRequestResult(KJob*)) );
kDebug() << "Requesting outbox folder.";
job->start();
}
// make sure we have a place to dump the sent mails as well
if ( !SpecialMailCollections::self()->hasDefaultCollection( SpecialMailCollections::SentMail ) ) {
SpecialMailCollectionsRequestJob *job = new SpecialMailCollectionsRequestJob( q );
job->requestDefaultCollection( SpecialMailCollections::SentMail );
kDebug() << "Requesting sent-mail folder";
job->start();
}
}
void OutboxQueue::Private::localFoldersRequestResult( KJob *job )
{
if ( job->error() ) {
// We tried to create the outbox, but that failed. This could be because some
// other process, the mail app, for example, tried to create it at the
// same time. So try again, once or twice, but wait a little in between, longer
// each time. If we still haven't managed to create it after a few retries,
// error hard.
if ( ++outboxDiscoveryRetries <= OUTBOX_DISCOVERY_RETRIES ) {
const int timeout = OUTBOX_DISCOVERY_WAIT_TIME * outboxDiscoveryRetries;
kWarning() << "Failed to get outbox folder. Retrying in: " << timeout;
QTimer::singleShot( timeout, q, SLOT(localFoldersChanged()) );
} else {
kWarning() << "Failed to get outbox folder. Giving up."; ;
emit q->error( i18n( "Could not access the outbox folder (%1).", job->errorString() ) );
}
return;
}
localFoldersChanged();
}
void OutboxQueue::Private::itemAdded( const Item &item )
{
addIfComplete( item );
}
void OutboxQueue::Private::itemChanged( const Item &item )
{
addIfComplete( item );
// TODO: if the item is moved out of the outbox, will I get itemChanged?
}
void OutboxQueue::Private::itemMoved( const Item &item, const Collection &source, const Collection &destination )
{
if ( source == outbox ) {
itemRemoved( item );
} else if ( destination == outbox ) {
addIfComplete( item );
}
}
void OutboxQueue::Private::itemRemoved( const Item &removedItem )
{
// @p item has size=0, so get the size from our own copy.
const int index = queue.indexOf( removedItem );
if ( index == -1 ) {
// Item was not in queue at all.
return;
}
Item item( queue.takeAt( index ) );
kDebug() << "Item" << item.id() << "(size" << item.size() << ") was removed from the queue.";
totalSize -= item.size();
futureItems.remove( removedItem );
}
void OutboxQueue::Private::itemProcessed( const Item &item, bool result )
{
Q_ASSERT( ignore.contains( item.id() ) );
if ( !result ) {
// Give the user a chance to re-send the item if it failed.
ignore.remove( item.id() );
}
}
OutboxQueue::OutboxQueue( QObject *parent )
: QObject( parent ),
d( new Private( this ) )
{
d->monitor = new Monitor( this );
d->monitor->itemFetchScope().fetchAllAttributes();
d->monitor->itemFetchScope().fetchFullPayload( false );
connect( d->monitor, SIGNAL(itemAdded(Akonadi::Item,Akonadi::Collection)),
this, SLOT(itemAdded(Akonadi::Item)) );
connect( d->monitor, SIGNAL(itemChanged(Akonadi::Item,QSet<QByteArray>)),
this, SLOT(itemChanged(Akonadi::Item)) );
connect( d->monitor, SIGNAL(itemMoved(Akonadi::Item,Akonadi::Collection,Akonadi::Collection)),
this, SLOT(itemMoved(Akonadi::Item,Akonadi::Collection,Akonadi::Collection)) );
connect( d->monitor, SIGNAL(itemRemoved(Akonadi::Item)),
this, SLOT(itemRemoved(Akonadi::Item)) );
connect( SpecialMailCollections::self(), SIGNAL(defaultCollectionsChanged()), this, SLOT(localFoldersChanged()) );
d->localFoldersChanged();
d->futureTimer = new QTimer( this );
connect( d->futureTimer, SIGNAL(timeout()), this, SLOT(checkFuture()) );
d->futureTimer->start( 60 * 60 * 1000 ); // 1 hour
}
OutboxQueue::~OutboxQueue()
{
delete d;
}
bool OutboxQueue::isEmpty() const
{
return d->queue.isEmpty();
}
int OutboxQueue::count() const
{
if ( d->queue.count() == 0 ) {
// TODO Is this asking for too much?
Q_ASSERT( d->totalSize == 0 );
}
return d->queue.count();
}
qulonglong OutboxQueue::totalSize() const
{
return d->totalSize;
}
void OutboxQueue::fetchOne()
{
if ( isEmpty() ) {
kDebug() << "Empty queue.";
return;
}
const Item item = d->queue.takeFirst();
d->totalSize -= item.size();
Q_ASSERT( !d->ignore.contains( item.id() ) );
d->ignore.insert( item.id() );
ItemFetchJob *job = new ItemFetchJob( item );
job->fetchScope().fetchAllAttributes();
job->fetchScope().fetchFullPayload();
connect( job, SIGNAL(result(KJob*)), this, SLOT(itemFetched(KJob*)) );
}
#include "moc_outboxqueue.cpp"

View file

@ -0,0 +1,96 @@
/*
Copyright (c) 2009 Constantin Berzan <exit3219@gmail.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 OUTBOXQUEUE_H
#define OUTBOXQUEUE_H
#include <QObject>
#include <Akonadi/Collection>
#include <Akonadi/Item>
class KJob;
/**
* @short Monitors the outbox collection and provides a queue of messages for the MDA to send.
*/
class OutboxQueue : public QObject
{
Q_OBJECT
friend class MailDispatcherAgent;
public:
/**
* Creates a new outbox queue.
*
* @param parent The parent object.
*/
explicit OutboxQueue( QObject *parent = 0 );
/**
* Destroys the outbox queue.
*/
virtual ~OutboxQueue();
/**
* Returns whether the queue is empty.
*/
bool isEmpty() const;
/**
* Returns the number of items in the queue.
*/
int count() const;
/**
* Returns the size (in bytes) of all items in the queue.
*/
qulonglong totalSize() const;
/**
* Fetches an item and emits itemReady() when done.
*/
void fetchOne();
Q_SIGNALS:
void itemReady( const Akonadi::Item &item );
void newItems();
void error( const QString &error );
private:
//@cond PRIVATE
class Private;
Private* const d;
Q_PRIVATE_SLOT( d, void checkFuture() )
Q_PRIVATE_SLOT( d, void collectionFetched( KJob* ) )
Q_PRIVATE_SLOT( d, void itemFetched( KJob* ) )
Q_PRIVATE_SLOT( d, void localFoldersChanged() )
Q_PRIVATE_SLOT( d, void localFoldersRequestResult( KJob* ) )
Q_PRIVATE_SLOT( d, void itemAdded( Akonadi::Item ) )
Q_PRIVATE_SLOT( d, void itemChanged( Akonadi::Item ) )
Q_PRIVATE_SLOT( d, void itemMoved( Akonadi::Item, Akonadi::Collection, Akonadi::Collection ) )
Q_PRIVATE_SLOT( d, void itemRemoved( Akonadi::Item ) )
Q_PRIVATE_SLOT( d, void itemProcessed( Akonadi::Item, bool ) )
//@endcond
};
#endif

View file

@ -0,0 +1,484 @@
/*
Copyright (c) 2009 Constantin Berzan <exit3219@gmail.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 "sendjob.h"
#include "storeresultjob.h"
#include <akonadi/agentinstance.h>
#include <akonadi/agentmanager.h>
#include <akonadi/collection.h>
#include <akonadi/dbusconnectionpool.h>
#include <akonadi/item.h>
#include <akonadi/itemdeletejob.h>
#include <akonadi/itemmodifyjob.h>
#include <akonadi/itemmovejob.h>
#include <akonadi/collectionfetchjob.h>
#include <akonadi/kmime/addressattribute.h>
#include <akonadi/kmime/messageparts.h>
#include <akonadi/kmime/specialmailcollections.h>
#include <akonadi/transportresourcebase.h>
#include <kdebug.h>
#include <klocalizedstring.h>
#include <kmime/kmime_message.h>
#include <mailtransport/sentbehaviourattribute.h>
#include <mailtransport/transport.h>
#include <mailtransport/transportattribute.h>
#include <mailtransport/transportjob.h>
#include <mailtransport/transportmanager.h>
#include <QtCore/QTimer>
#include <QtDBus/QDBusInterface>
#include <QtDBus/QDBusReply>
#include <boost/shared_ptr.hpp>
using namespace Akonadi;
using namespace KMime;
using namespace MailTransport;
/**
* Private class that helps to provide binary compatibility between releases.
* @internal
*/
class SendJob::Private
{
public:
Private( const Item &itm, SendJob *qq )
: q( qq ),
item( itm ),
currentJob( 0 ),
interface( 0 ),
mailfilterInterface( 0 ),
aborting( false )
{
}
SendJob *const q;
Item item;
KJob *currentJob;
QString resourceId;
QDBusInterface *interface;
QDBusInterface *mailfilterInterface;
bool aborting;
void doAkonadiTransport();
void doTraditionalTransport();
void doPostJob( bool transportSuccess, const QString &transportMessage );
void storeResult( bool success, const QString &message = QString() );
void abortPostJob();
bool filterItem( int filterset );
// slots
void doTransport();
void transportPercent( KJob *job, unsigned long percent );
void transportResult( KJob *job );
void resourceProgress( const AgentInstance &instance );
void resourceResult( qlonglong itemId, int result, const QString &message );
void postJobResult( KJob *job );
void doEmitResult( KJob *job );
void slotSentMailCollectionFetched( KJob *job );
};
void SendJob::Private::doTransport()
{
kDebug() << "Transporting message.";
if ( aborting ) {
kDebug() << "Marking message as aborted.";
q->setError( UserDefinedError );
q->setErrorText( i18n( "Message sending aborted." ) );
storeResult( false, i18n( "Message sending aborted." ) );
return;
}
// Is it an Akonadi transport or a traditional one?
const TransportAttribute *transportAttribute = item.attribute<TransportAttribute>();
Q_ASSERT( transportAttribute );
if ( !transportAttribute->transport() ) {
storeResult( false, i18n( "Could not initiate message transport. Possibly invalid transport." ) );
return;
}
const TransportType type = transportAttribute->transport()->transportType();
if ( !type.isValid() ) {
storeResult( false, i18n( "Could not send message. Invalid transport." ) );
return;
}
if ( !filterItem( 8 ) ) //BeforeOutbound
return;
if ( type.type() == Transport::EnumType::Akonadi ) {
// Send the item directly to the resource that will send it.
resourceId = transportAttribute->transport()->host();
doAkonadiTransport();
} else {
// Use a traditional transport job.
doTraditionalTransport();
}
}
void SendJob::Private::doAkonadiTransport()
{
Q_ASSERT( !resourceId.isEmpty() );
Q_ASSERT( interface == 0 );
interface = new QDBusInterface(
QLatin1String( "org.freedesktop.Akonadi.Resource." ) + resourceId,
QLatin1String( "/Transport" ), QLatin1String( "org.freedesktop.Akonadi.Resource.Transport" ),
DBusConnectionPool::threadConnection(), q );
if ( !interface->isValid() ) {
storeResult( false, i18n( "Failed to get D-Bus interface of resource %1.", resourceId ) );
delete interface;
interface = 0;
return;
}
// Signals.
QObject::connect( AgentManager::self(), SIGNAL(instanceProgressChanged(Akonadi::AgentInstance)),
q, SLOT(resourceProgress(Akonadi::AgentInstance)) );
QObject::connect( interface, SIGNAL(transportResult(qlonglong,int,QString)),
q, SLOT(resourceResult(qlonglong,int,QString)) );
// Start sending.
const QDBusReply<void> reply = interface->call( QLatin1String( "send" ), item.id() );
if ( !reply.isValid() ) {
storeResult( false, i18n( "Invalid D-Bus reply from resource %1.", resourceId ) );
return;
}
}
void SendJob::Private::doTraditionalTransport()
{
const TransportAttribute *transportAttribute = item.attribute<TransportAttribute>();
TransportJob *job = TransportManager::self()->createTransportJob( transportAttribute->transportId() );
Q_ASSERT( job );
Q_ASSERT( currentJob == 0 );
currentJob = job;
// Message.
Q_ASSERT( item.hasPayload<Message::Ptr>() );
const Message::Ptr message = item.payload<Message::Ptr>();
bool needAssemble = false;
if ( message->hasHeader( "Bcc" ) ) {
message->removeHeader( "Bcc" );
needAssemble = true;
}
if( message->hasHeader( "X-KMail-Identity" ) ) {
message->removeHeader( "X-KMail-Identity" );
needAssemble = true;
}
if(needAssemble) {
message->assemble();
}
const QByteArray content = message->encodedContent( true ) + "\r\n";
Q_ASSERT( !content.isEmpty() );
// Addresses.
const AddressAttribute *addressAttribute = item.attribute<AddressAttribute>();
Q_ASSERT( addressAttribute );
job->setData( content );
job->setSender( addressAttribute->from() );
job->setTo( addressAttribute->to() );
job->setCc( addressAttribute->cc() );
job->setBcc( addressAttribute->bcc() );
// Signals.
connect( job, SIGNAL(result(KJob*)),
q, SLOT(transportResult(KJob*)) );
connect( job, SIGNAL(percent(KJob*,ulong)),
q, SLOT(transportPercent(KJob*,ulong)) );
job->start();
}
void SendJob::Private::transportPercent( KJob *job, unsigned long )
{
Q_ASSERT( currentJob == job );
kDebug() << "Processed amount" << job->processedAmount( KJob::Bytes )
<< "total amount" << job->totalAmount( KJob::Bytes );
q->setTotalAmount( KJob::Bytes, job->totalAmount( KJob::Bytes ) ); // Is not set at the time of start().
q->setProcessedAmount( KJob::Bytes, job->processedAmount( KJob::Bytes ) );
}
void SendJob::Private::transportResult( KJob *job )
{
Q_ASSERT( currentJob == job );
currentJob = 0;
doPostJob( !job->error(), job->errorString() );
}
void SendJob::Private::resourceProgress( const AgentInstance &instance )
{
if ( !interface ) {
// We might have gotten a very late signal.
kWarning() << "called but no resource job running!";
return;
}
if ( instance.identifier() == resourceId ) {
// This relies on the resource's progress representing the progress of
// sending this item.
q->setPercent( instance.progress() );
}
}
void SendJob::Private::resourceResult( qlonglong itemId, int result,
const QString &message )
{
Q_UNUSED( itemId );
Q_ASSERT( interface );
delete interface; // So that abort() knows the transport job is over.
interface = 0;
const TransportResourceBase::TransportResult transportResult =
static_cast<TransportResourceBase::TransportResult>( result );
const bool success = ( transportResult == TransportResourceBase::TransportSucceeded );
Q_ASSERT( itemId == item.id() );
doPostJob( success, message );
}
void SendJob::Private::abortPostJob()
{
// We were unlucky and LocalFolders is recreating its stuff right now.
// We will not wait for it.
kWarning() << "Default sent mail collection unavailable, not moving the mail after sending.";
q->setError( UserDefinedError );
q->setErrorText( i18n( "Default sent-mail folder unavailable. Keeping message in outbox." ) );
storeResult( false, q->errorString() );
}
void SendJob::Private::doPostJob( bool transportSuccess, const QString &transportMessage )
{
kDebug() << "success" << transportSuccess << "message" << transportMessage;
if ( !transportSuccess ) {
kDebug() << "Error transporting.";
q->setError( UserDefinedError );
const QString error = aborting ? i18n( "Message transport aborted." )
: i18n( "Failed to transport message." );
q->setErrorText( error + QLatin1Char(' ') + transportMessage );
storeResult( false, q->errorString() );
} else {
kDebug() << "Success transporting.";
// Delete or move to sent-mail.
const SentBehaviourAttribute *attribute = item.attribute<SentBehaviourAttribute>();
Q_ASSERT( attribute );
if ( attribute->sentBehaviour() == SentBehaviourAttribute::Delete ) {
kDebug() << "Deleting item from outbox.";
currentJob = new ItemDeleteJob( item );
QObject::connect( currentJob, SIGNAL(result(KJob*)), q, SLOT(postJobResult(KJob*)) );
} else {
if ( attribute->sentBehaviour() == SentBehaviourAttribute::MoveToDefaultSentCollection ) {
if ( SpecialMailCollections::self()->hasDefaultCollection( SpecialMailCollections::SentMail ) ) {
currentJob = new ItemMoveJob( item, SpecialMailCollections::self()->defaultCollection( SpecialMailCollections::SentMail ) , q );
QObject::connect( currentJob, SIGNAL(result(KJob*)), q, SLOT(postJobResult(KJob*)) );
} else {
abortPostJob();
}
} else {
kDebug() << "sentBehaviour=" << attribute->sentBehaviour() << "using collection from attribute";
currentJob = new CollectionFetchJob( attribute->moveToCollection(), Akonadi::CollectionFetchJob::Base );
QObject::connect( currentJob, SIGNAL(result(KJob*)),
q, SLOT(slotSentMailCollectionFetched(KJob*)) );
}
}
}
}
bool SendJob::Private::filterItem( int filterset )
{
Q_ASSERT( mailfilterInterface == 0 );
// TODO: create on stack
mailfilterInterface = new QDBusInterface(
QLatin1String( "org.freedesktop.Akonadi.MailFilterAgent" ),
QLatin1String( "/MailFilterAgent" ), QLatin1String( "org.freedesktop.Akonadi.MailFilterAgent" ),
DBusConnectionPool::threadConnection(), q );
if ( !mailfilterInterface->isValid() ) {
storeResult( false, i18n( "Failed to get D-Bus interface of mailfilteragent." ) );
delete mailfilterInterface;
mailfilterInterface = 0;
return false;
}
//Outbound = 0x2
const QDBusReply<void> reply = mailfilterInterface->call( QLatin1String( "filterItem" ), item.id(), filterset, QString() );
if ( !reply.isValid() ) {
storeResult( false, i18n( "Invalid D-Bus reply from mailfilteragent" ) );
delete mailfilterInterface;
mailfilterInterface = 0;
return false;
}
delete mailfilterInterface;
mailfilterInterface = 0;
return true;
}
void SendJob::Private::slotSentMailCollectionFetched(KJob* job)
{
Akonadi::Collection fetchCol;
bool ok = false;
if ( !job->error() ) {
const CollectionFetchJob *const fetchJob = qobject_cast<CollectionFetchJob*>( job );
if ( !fetchJob->collections().isEmpty() ) {
fetchCol = fetchJob->collections().first();
ok = true;
}
}
if ( !ok ) {
if ( !SpecialMailCollections::self()->hasDefaultCollection( SpecialMailCollections::SentMail ) ) {
abortPostJob();
return;
}
fetchCol = SpecialMailCollections::self()->defaultCollection( SpecialMailCollections::SentMail );
}
currentJob = new ItemMoveJob( item, fetchCol, q );
QObject::connect( currentJob, SIGNAL(result(KJob*)), q, SLOT(postJobResult(KJob*)) );
}
void SendJob::Private::postJobResult( KJob *job )
{
Q_ASSERT( currentJob == job );
currentJob = 0;
const SentBehaviourAttribute *attribute = item.attribute<SentBehaviourAttribute>();
Q_ASSERT( attribute );
if ( job->error() ) {
kDebug() << "Error deleting or moving to sent-mail.";
QString errorString;
switch( attribute->sentBehaviour() ) {
case SentBehaviourAttribute::Delete:
errorString =
i18n( "Sending succeeded, but failed to remove the message from the outbox." );
break;
default:
errorString =
i18n( "Sending succeeded, but failed to move the message to the sent-mail folder." );
break;
}
q->setError( UserDefinedError );
q->setErrorText( errorString + QLatin1Char(' ') + job->errorString() );
storeResult( false, q->errorString() );
} else {
kDebug() << "Success deleting or moving to sent-mail.";
if ( !filterItem( 2 ) ) //Outbound
return;
if ( attribute->sentBehaviour() == SentBehaviourAttribute::Delete )
q->emitResult();
else
storeResult( true );
}
}
void SendJob::Private::storeResult( bool success, const QString &message )
{
kDebug() << "success" << success << "message" << message;
Q_ASSERT( currentJob == 0 );
currentJob = new StoreResultJob( item, success, message );
connect( currentJob, SIGNAL(result(KJob*)), q, SLOT(doEmitResult(KJob*)) );
}
void SendJob::Private::doEmitResult( KJob *job )
{
Q_ASSERT( currentJob == job );
currentJob = 0;
if ( job->error() ) {
kWarning() << "Error storing result.";
q->setError( UserDefinedError );
q->setErrorText( q->errorString() + QLatin1Char(' ') + i18n( "Failed to store result in item." ) + QLatin1Char(' ') + job->errorString() );
} else {
kDebug() << "Success storing result.";
// It is still possible that the transport failed.
StoreResultJob* srJob = static_cast<StoreResultJob *>( job );
if ( !srJob->success() ) {
q->setError( UserDefinedError );
q->setErrorText( srJob->message() );
}
}
q->emitResult();
}
SendJob::SendJob( const Item &item, QObject *parent )
: KJob( parent ),
d( new Private( item, this ) )
{
}
SendJob::~SendJob()
{
delete d;
}
void SendJob::start()
{
QTimer::singleShot( 0, this, SLOT(doTransport()) );
}
void SendJob::setMarkAborted()
{
Q_ASSERT( !d->aborting );
d->aborting = true;
}
void SendJob::abort()
{
setMarkAborted();
if ( dynamic_cast<TransportJob*>( d->currentJob ) ) {
kDebug() << "Abort called, active transport job.";
// Abort transport.
d->currentJob->kill( KJob::EmitResult );
} else if ( d->interface != 0 ) {
kDebug() << "Abort called, propagating to resource.";
// Abort resource doing transport.
AgentInstance instance = AgentManager::self()->instance( d->resourceId );
instance.abortCurrentTask();
} else {
kDebug() << "Abort called, but no transport job is active.";
// Either transport has not started, in which case doTransport will
// mark the item as aborted, or the item has already been sent, in which
// case there is nothing we can do.
}
}
#include "moc_sendjob.cpp"

View file

@ -0,0 +1,91 @@
/*
Copyright (c) 2009 Constantin Berzan <exit3219@gmail.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 SENDJOB_H
#define SENDJOB_H
#include <KJob>
namespace Akonadi {
class Item;
}
/**
* @short A job to send a mail
*
* This class takes a prevalidated Item with all the required attributes,
* sends it using MailTransport, and then stores the result of the sending
* operation in the item.
*/
class SendJob : public KJob
{
Q_OBJECT
public:
/**
* Creates a new send job.
*
* @param item The item to send.
* @param parent The parent object.
*/
explicit SendJob( const Akonadi::Item &item, QObject *parent = 0 );
/**
* Destroys the send job.
*/
virtual ~SendJob();
/**
* Starts the job.
*/
virtual void start();
/**
* If this function is called before the job is started, the SendJob will
* just mark the item as aborted, instead of sending it.
* Do not call this function more than once.
*/
void setMarkAborted();
/**
* Aborts sending the item.
*
* This will give the item an ErrorAttribute of "aborted".
* (No need to call setMarkAborted() if you call abort().)
*/
void abort();
private:
//@cond PRIVATE
class Private;
Private *const d;
Q_PRIVATE_SLOT( d, void doTransport() )
Q_PRIVATE_SLOT( d, void transportPercent( KJob*, unsigned long ) )
Q_PRIVATE_SLOT( d, void transportResult( KJob* ) )
Q_PRIVATE_SLOT( d, void resourceProgress( const Akonadi::AgentInstance& ) )
Q_PRIVATE_SLOT( d, void resourceResult( qlonglong, int, const QString& ) )
Q_PRIVATE_SLOT( d, void postJobResult( KJob* ) )
Q_PRIVATE_SLOT( d, void doEmitResult( KJob* ) )
Q_PRIVATE_SLOT( d, void slotSentMailCollectionFetched( KJob* ) )
//@endcond
};
#endif

View file

@ -0,0 +1,70 @@
/*
Copyright (C) 2010 Klarälvdalens Datakonsult AB,
a KDAB Group company, info@kdab.net,
author Tobias Koenig <tokoe@kdab.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 "sentactionhandler.h"
#include <akonadi/itemfetchjob.h>
#include <akonadi/itemmodifyjob.h>
#include <akonadi/kmime/messageflags.h>
using namespace MailTransport;
SentActionHandler::SentActionHandler( QObject *parent )
: QObject( parent )
{
}
void SentActionHandler::runAction( const SentActionAttribute::Action &action )
{
if ( action.type() == SentActionAttribute::Action::MarkAsReplied ||
action.type() == SentActionAttribute::Action::MarkAsForwarded ) {
const Akonadi::Item item( action.value().toLongLong() );
Akonadi::ItemFetchJob *job = new Akonadi::ItemFetchJob( item );
connect( job, SIGNAL(result(KJob*)), SLOT(itemFetchResult(KJob*)) );
job->setProperty( "type", static_cast<int>( action.type() ) );
}
}
void SentActionHandler::itemFetchResult( KJob *job )
{
if ( job->error() ) {
kWarning() << job->errorText();
return;
}
Akonadi::ItemFetchJob *fetchJob = qobject_cast<Akonadi::ItemFetchJob*>( job );
if ( fetchJob->items().isEmpty() )
return;
Akonadi::Item item = fetchJob->items().first();
const SentActionAttribute::Action::Type type = static_cast<SentActionAttribute::Action::Type>( job->property( "type" ).toInt() );
if ( type == SentActionAttribute::Action::MarkAsReplied ) {
item.setFlag( Akonadi::MessageFlags::Replied );
} else if ( type == SentActionAttribute::Action::MarkAsForwarded ) {
item.setFlag( Akonadi::MessageFlags::Forwarded );
}
Akonadi::ItemModifyJob *modifyJob = new Akonadi::ItemModifyJob( item );
modifyJob->setIgnorePayload( true );
}

View file

@ -0,0 +1,44 @@
/*
Copyright (C) 2010 Klarälvdalens Datakonsult AB,
a KDAB Group company, info@kdab.net,
author Tobias Koenig <tokoe@kdab.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 SENTACTIONHANDLER_H
#define SENTACTIONHANDLER_H
#include <mailtransport/sentactionattribute.h>
#include <QtCore/QObject>
class KJob;
class SentActionHandler : public QObject
{
Q_OBJECT
public:
explicit SentActionHandler( QObject *parent = 0 );
void runAction( const MailTransport::SentActionAttribute::Action &action );
private Q_SLOTS:
void itemFetchResult( KJob *job );
};
#endif

View file

@ -0,0 +1,8 @@
File=maildispatcheragent.kcfg
ClassName=Settings
Mutators=true
ItemAccessors=true
SetUserTexts=true
Singleton=true
#IncludeFiles=
GlobalEnums=true

View file

@ -0,0 +1,77 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<author>Till Adam &lt;adam@kde.org&gt;</author>
<class>ConfigDialog</class>
<widget class="QWidget" name="ConfigDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>250</height>
</rect>
</property>
<property name="windowTitle">
<string>Mail Dispatcher Agent Settings</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Select the collection to be used as outbox:</string>
</property>
</widget>
</item>
<item>
<widget class="Akonadi::CollectionRequester" name="outboxSelector">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Select the collection to move sent messages into:</string>
</property>
</widget>
</item>
<item>
<widget class="Akonadi::CollectionRequester" name="sentMailSelector">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>13</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>Akonadi::CollectionRequester</class>
<extends>QFrame</extends>
<header>akonadi/collectionrequester.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View file

@ -0,0 +1,140 @@
/*
Copyright (c) 2009 Constantin Berzan <exit3219@gmail.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 "storeresultjob.h"
#include <Akonadi/Item>
#include <Akonadi/ItemFetchJob>
#include <Akonadi/ItemModifyJob>
#include <akonadi/kmime/messageflags.h>
#include <KDebug>
#include <KLocalizedString>
#include <mailtransport/errorattribute.h>
#include <mailtransport/dispatchmodeattribute.h>
using namespace Akonadi;
using namespace MailTransport;
/**
* @internal
*/
class StoreResultJob::Private
{
public:
Private( StoreResultJob *qq )
: q( qq ), success( false )
{
}
StoreResultJob *const q;
Item item;
bool success;
QString message;
// slots:
void fetchDone( KJob *job );
void modifyDone( KJob *job );
};
void StoreResultJob::Private::fetchDone( KJob *job )
{
if ( job->error() )
return;
kDebug();
const ItemFetchJob *fetchJob = qobject_cast<ItemFetchJob*>( job );
Q_ASSERT( fetchJob );
if ( fetchJob->items().count() != 1 ) {
kError() << "Fetched" << fetchJob->items().count() << "items, expected 1.";
q->setError( Unknown );
q->setErrorText( i18n( "Failed to fetch item." ) );
q->commit();
return;
}
// Store result in item.
Item item = fetchJob->items().first();
if ( success ) {
item.clearFlag( Akonadi::MessageFlags::Queued );
item.setFlag( Akonadi::MessageFlags::Sent );
item.setFlag( Akonadi::MessageFlags::Seen );
} else {
item.setFlag( Akonadi::MessageFlags::HasError );
ErrorAttribute *errorAttribute = new ErrorAttribute( message );
item.addAttribute( errorAttribute );
// If dispatch failed, set the DispatchModeAttribute to Manual.
// Otherwise, the user will *never* be able to try sending the mail again,
// as Send Queued Messages will ignore it.
if ( item.hasAttribute<DispatchModeAttribute>() ) {
item.attribute<DispatchModeAttribute>()->setDispatchMode( MailTransport::DispatchModeAttribute::Manual );
} else {
item.addAttribute( new DispatchModeAttribute( MailTransport::DispatchModeAttribute::Manual ) );
}
}
ItemModifyJob *modifyJob = new ItemModifyJob( item, q );
QObject::connect( modifyJob, SIGNAL(result(KJob*)), q, SLOT(modifyDone(KJob*)) );
}
void StoreResultJob::Private::modifyDone( KJob *job )
{
if ( job->error() )
return;
kDebug();
q->commit();
}
StoreResultJob::StoreResultJob( const Item &item, bool success, const QString &message, QObject *parent )
: TransactionSequence( parent ),
d( new Private( this ) )
{
d->item = item;
d->success = success;
d->message = message;
}
StoreResultJob::~StoreResultJob()
{
delete d;
}
void StoreResultJob::doStart()
{
// Fetch item in case it was modified elsewhere.
ItemFetchJob *job = new ItemFetchJob( d->item, this );
connect( job, SIGNAL(result(KJob*)), this, SLOT(fetchDone(KJob*)) );
}
bool StoreResultJob::success() const
{
return d->success;
}
QString StoreResultJob::message() const
{
return d->message;
}
#include "moc_storeresultjob.cpp"

View file

@ -0,0 +1,74 @@
/*
Copyright (c) 2009 Constantin Berzan <exit3219@gmail.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 STORERESULTJOB_H
#define STORERESULTJOB_H
#include <Akonadi/TransactionSequence>
#include <QtCore/QString>
namespace Akonadi {
class Item;
}
/**
* This class stores the result of a StoreResultJob in an item.
* First, it removes the 'queued' flag.
* After that, if the result was success, it stores the 'sent' flag.
* If the result was failure, it stores the 'error' flag and an ErrorAttribute.
*/
class StoreResultJob : public Akonadi::TransactionSequence
{
Q_OBJECT
public:
/**
* Creates a new store result job.
*
* @param item The item to store.
* @param success Whether the mail could be dispatched or not.
* @param message An error message in case the mail could not be dispatched.
* @param parent The parent object.
*/
explicit StoreResultJob( const Akonadi::Item &item, bool success, const QString &message, QObject *parent = 0 );
/**
* Destroys the store result job.
*/
virtual ~StoreResultJob();
bool success() const;
QString message() const;
protected:
// reimpl from TransactionSequence
virtual void doStart();
private:
//@cond PRIVATE
class Private;
Private *const d;
Q_PRIVATE_SLOT( d, void fetchDone( KJob *job ) )
Q_PRIVATE_SLOT( d, void modifyDone( KJob *job ) )
//@endcond
};
#endif

View file

@ -0,0 +1,43 @@
set( EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR} )
# Stolen from kdepimlibs/akonadi/tests
macro(add_akonadi_isolated_test _source)
get_filename_component(_targetName ${_source} NAME_WE)
set(_srcList ${_source} )
kde4_add_executable(${_targetName} TEST ${_srcList})
target_link_libraries(${_targetName}
${QT_QTTEST_LIBRARY}
${QT_QTGUI_LIBRARY}
${KDEPIMLIBS_AKONADI_LIBS}
${KDEPIMLIBS_AKONADI_KMIME_LIBS}
${KDE4_KDECORE_LIBS}
${KDEPIMLIBS_MAILTRANSPORT_LIBS}
${KDEPIMLIBS_KMIME_LIBS}
${QT_QTCORE_LIBRARY}
${QT_QTDBUS_LIBRARY}
)
# based on kde4_add_unit_test
if (WIN32)
get_target_property( _loc ${_targetName} LOCATION )
set(_executable ${_loc}.bat)
else ()
set(_executable ${EXECUTABLE_OUTPUT_PATH}/${_targetName})
endif ()
if (UNIX)
set(_executable ${_executable}.shell)
endif ()
find_program(_testrunner akonaditest)
if (KDEPIM_RUN_ISOLATED_TESTS)
add_test( maildispatcheragent-${_targetName} ${_testrunner} -c ${CMAKE_CURRENT_SOURCE_DIR}/unittestenv/config.xml ${_executable} )
endif ()
endmacro(add_akonadi_isolated_test)
add_akonadi_isolated_test( aborttest.cpp )
add_akonadi_isolated_test( dupetest.cpp )

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