[Libreoffice-commits] core.git: Branch 'private/jmux/kde5' - 245 commits - android/source autogen.sh avmedia/source basctl/source basic/source bin/gbuild-to-ide bin/get-bugzilla-attachments-by-mimetype chart2/inc chart2/source chart2/uiconfig comphelper/source comphelper/util config_host/config_kde4.h.in config_host/config_kde5.h.in config_host/config_vclplug.h.in config_host.mk.in configmgr/qa configure.ac connectivity/source cui/Library_cui.mk cui/source cui/uiconfig cui/UIConfig_cui.mk dbaccess/source desktop/source dictionaries distro-configs/LibreOfficeCoverity.conf download.lst drawinglayer/source editeng/source embeddedobj/source eventattacher/source extensions/Library_log.mk extensions/source external/libodfgen external/librevenge external/libvisio external/libwpd external/libwpg filter/source forms/source fpicker/source framework/inc framework/source helpcontent2 hwpfilter/source icon-themes/tango idlc/inc idlc/source include/avmedia include/basic include/comphelper include/connectivity include/editeng include/filter include/oox include/sfx2 include/svtools include/svx include/test include/toolkit include/unotools include/vbahelper include/vcl include/xmloff javaunohelper/com jurt/com l10ntools/source libreofficekit/source lotuswordpro/source mysqlc/source officecfg/registry oox/source package/inc package/source postprocess/Rdb_services.mk qadevOOo/runner qadevOOo/tests reportdesign/source RepositoryExternal.mk Repository.mk sax/qa sc/AllLangResTarget_sc.mk sc/inc scp2/InstallModule_ooo.mk scp2/InstallScript_setup_osl.mk scp2/Module_scp2.mk sc/qa scripting/source sc/sdi sc/source sc/uiconfig sc/UIConfig_scalc.mk sdext/source sd/qa sd/sdi sd/source sd/uiconfig sfx2/sdi sfx2/source shell/Library_kde5be.mk shell/Module_shell.mk shell/source slideshow/source solenv/gbuild solenv/gdb starmath/inc starmath/qa starmath/source svtools/source svx/sdi svx/source sw/inc sw/qa sw/sdi sw/source sw/uiconfig sysui/CustomTarget_share.mk test/source tubes/source ucb/source unotools /source unusedcode.easy unusedcode.exclude vcl/CustomTarget_kde5_moc.mk vcl/CustomTarget_tde_moc.mk vcl/generic vcl/headless vcl/inc vcl/Library_vclplug_kde4.mk vcl/Library_vclplug_kde5.mk vcl/Module_vcl.mk vcl/opengl vcl/Package_opengl.mk vcl/quartz vcl/source vcl/unx vcl/win vcl/workben wizards/com wizards/source xmerge/source xmloff/source xmlscript/source

Jan-Marek Glogowski glogow at fbihome.de
Fri Jan 1 19:34:42 PST 2016


Rebased ref, commits from common ancestor:
commit bb052df12007ca4c57b8753c25c9212fdd4146bf
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Fri Dec 11 21:57:44 2015 +0100

    KDE5
    
    Change-Id: I8ccdf61dd210e77dd78ac685863092dd37c90a59

diff --git a/Repository.mk b/Repository.mk
index 5c468b2..b7e2da3 100644
--- a/Repository.mk
+++ b/Repository.mk
@@ -256,8 +256,10 @@ $(eval $(call gb_Helper_register_libraries_for_install,OOOLIBS,gnome, \
 
 $(eval $(call gb_Helper_register_libraries_for_install,OOOLIBS,kde, \
 	$(if $(ENABLE_KDE4),kde4be1) \
+	$(if $(ENABLE_KDE5),kde5be1) \
 	$(if $(USING_X11), \
 		$(if $(ENABLE_KDE4),vclplug_kde4) \
+		$(if $(ENABLE_KDE5),vclplug_kde5) \
 	) \
 ))
 
diff --git a/RepositoryExternal.mk b/RepositoryExternal.mk
index fe614db3..61b1b2c 100644
--- a/RepositoryExternal.mk
+++ b/RepositoryExternal.mk
@@ -2982,6 +2982,39 @@ endef
 endif # ENABLE_KDE4
 
 
+ifeq ($(ENABLE_KDE5),TRUE)
+
+define gb_LinkTarget__use_kde5
+$(call gb_LinkTarget_set_include,$(1),\
+	$(subst -isystem/,-isystem /,$(filter -I% -isystem%,$(subst -isystem /,-isystem/,$(KF5_CFLAGS)))) \
+	$$(INCLUDE) \
+)
+
+$(call gb_LinkTarget_add_defs,$(1),\
+	$(filter-out -I% -isystem%,$(subst -isystem /,-isystem/,$(KF5_CFLAGS))) \
+)
+
+$(call gb_LinkTarget_add_libs,$(1),\
+	$(KF5_LIBS) \
+)
+
+ifeq ($(COM),GCC)
+$(call gb_LinkTarget_add_cxxflags,$(1),\
+	-Wno-shadow \
+)
+endif
+
+endef
+
+else # !ENABLE_KDE5
+
+define gb_LinkTarget__use_kde5
+
+endef
+
+endif # ENABLE_KDE5
+
+
 ifeq ($(ENABLE_TDE),TRUE)
 
 define gb_LinkTarget__use_tde
diff --git a/config_host.mk.in b/config_host.mk.in
index 0fc29b6..1729019 100644
--- a/config_host.mk.in
+++ b/config_host.mk.in
@@ -144,6 +144,7 @@ export ENABLE_GTK_PRINT=@ENABLE_GTK_PRINT@
 export ENABLE_HEADLESS=@ENABLE_HEADLESS@
 export ENABLE_JAVA=@ENABLE_JAVA@
 export ENABLE_KDE4=@ENABLE_KDE4@
+export ENABLE_KDE5=@ENABLE_KDE5@
 export ENABLE_LIBLANGTAG=@ENABLE_LIBLANGTAG@
 export ENABLE_LPSOLVE=@ENABLE_LPSOLVE@
 export ENABLE_LTO=@ENABLE_LTO@
@@ -306,6 +307,11 @@ export KDE4_LIBS=$(gb_SPACE)@KDE4_LIBS@
 export KDE4_GLIB_CFLAGS=$(gb_SPACE)@KDE4_GLIB_CFLAGS@
 export KDE4_GLIB_LIBS=$(gb_SPACE)@KDE4_GLIB_LIBS@
 export KDE4_HAVE_GLIB=@KDE4_HAVE_GLIB@
+export KF5_CFLAGS=$(gb_SPACE)@KF5_CFLAGS@
+export KF5_LIBS=$(gb_SPACE)@KF5_LIBS@
+export KF5_GLIB_CFLAGS=$(gb_SPACE)@KF5_GLIB_CFLAGS@
+export KF5_GLIB_LIBS=$(gb_SPACE)@KF5_GLIB_LIBS@
+export KF5_HAVE_GLIB=@KF5_HAVE_GLIB@
 export KRB5_LIBS=@KRB5_LIBS@
 export LCMS2_CFLAGS=$(gb_SPACE)@LCMS2_CFLAGS@
 export LCMS2_LIBS=$(gb_SPACE)@LCMS2_LIBS@
@@ -397,6 +403,7 @@ export MINGW_SHARED_LIBSTDCPP=@MINGW_SHARED_LIBSTDCPP@
 export MINGW_SYSROOT=@MINGW_SYSROOT@
 export ML_EXE=@ML_EXE@
 export MOC4=@MOC4@
+export MOC5=@MOC5@
 export MPL_SUBSET=@MPL_SUBSET@
 export MSM_PATH=@MSM_PATH@
 export MSPUB_CFLAGS=$(gb_SPACE)@MSPUB_CFLAGS@
diff --git a/config_host/config_kde5.h.in b/config_host/config_kde5.h.in
new file mode 100644
index 0000000..01fa9d2
--- /dev/null
+++ b/config_host/config_kde5.h.in
@@ -0,0 +1,10 @@
+/*
+Settings for KDE5 integration.
+*/
+
+#ifndef CONFIG_KDE5_H
+#define CONFIG_KDE5_H
+
+#define KF5_HAVE_GLIB 0
+
+#endif
diff --git a/config_host/config_vclplug.h.in b/config_host/config_vclplug.h.in
index ae17474..75558b5 100644
--- a/config_host/config_vclplug.h.in
+++ b/config_host/config_vclplug.h.in
@@ -9,6 +9,7 @@ Settings about which X11 desktops have support enabled.
 
 #define ENABLE_GTK 0
 #define ENABLE_KDE4 0
+#define ENABLE_KDE5 0
 #define ENABLE_TDE 0
 #define ENABLE_GIO 0
 
diff --git a/configure.ac b/configure.ac
index fa441c3..6d80f45 100644
--- a/configure.ac
+++ b/configure.ac
@@ -641,6 +641,7 @@ linux-gnu*|k*bsd*-gnu*)
     build_gstreamer_0_10=yes
     test_tde=yes
     test_kde4=yes
+    test_kde5=yes
     test_freetype=yes
     _os=Linux
     ;;
@@ -737,6 +738,7 @@ freebsd*)
     build_gstreamer_0_10=yes
     test_tde=yes
     test_kde4=yes
+    test_kde5=yes
     test_freetype=yes
     AC_MSG_CHECKING([the FreeBSD operating system release])
     if test -n "$with_os_version"; then
@@ -766,6 +768,7 @@ freebsd*)
     build_gstreamer_0_10=yes
     test_tde=no
     test_kde4=yes
+    test_kde5=yes
     test_freetype=yes
     PTHREAD_LIBS="-pthread -lpthread"
     _os=NetBSD
@@ -793,6 +796,7 @@ dragonfly*)
     build_gstreamer_0_10=yes
     test_tde=yes
     test_kde4=yes
+    test_kde5=yes
     test_freetype=yes
     PTHREAD_LIBS="-pthread"
     _os=DragonFly
@@ -814,6 +818,7 @@ linux-android*)
     test_gtk=no
     test_tde=no
     test_kde4=no
+    test_kde5=no
     test_randr=no
     test_xrender=no
     _os=Android
@@ -1248,6 +1253,12 @@ AC_ARG_ENABLE(kde4,
          KDE4 are available.]),
 ,)
 
+AC_ARG_ENABLE(kde5,
+    AS_HELP_STRING([--enable-kde5],
+        [Determines whether to use Qt5/KF5 vclplug on platforms where Qt5 and
+         KF5 are available.]),
+,)
+
 AC_ARG_ENABLE(randr,
     AS_HELP_STRING([--disable-randr],
         [Disable RandR support in the vcl project.]),
@@ -4777,6 +4788,7 @@ if test "$USING_X11" != TRUE; then
     build_gstreamer_0_10=no
     test_tde=no
     test_kde4=no
+    test_kde5=no
     enable_cairo_canvas=no
 fi
 
@@ -10032,6 +10044,14 @@ if test "x$enable_kde4" = "xyes"; then
 fi
 AC_SUBST(ENABLE_KDE4)
 
+ENABLE_KDE5=""
+if test "x$enable_kde5" = "xyes"; then
+    ENABLE_KDE5="TRUE"
+    AC_DEFINE(ENABLE_KDE5)
+    R="$R kde5"
+fi
+AC_SUBST(ENABLE_KDE5)
+
 ENABLE_HEADLESS=""
 if test "x$with_x" = "xno" -o "$CXX" = "emcc"; then
     ENABLE_HEADLESS="TRUE"
@@ -11258,6 +11278,243 @@ AC_SUBST(KDE4_GLIB_LIBS)
 AC_SUBST(KDE4_HAVE_GLIB)
 
 dnl ===================================================================
+dnl KDE5 Integration
+dnl ===================================================================
+
+KF5_CFLAGS=""
+KF5_LIBS=""
+QMAKE5="qmake"
+KF5_CONFIG="kf5-config"
+MOC5="moc"
+KF5_GLIB_CFLAGS=""
+KF5_GLIB_LIBS=""
+KF5_HAVE_GLIB=""
+if test "$test_kde5" = "yes" -a "$ENABLE_KDE5" = "TRUE"; then
+    qt5_incdirs="$QT5INC /usr/include/qt5 /usr/include $x_includes"
+    qt5_libdirs="$QT5LIB /usr/lib/qt5 /usr/lib $x_libraries"
+
+    kf5_incdirs="$KF5INC /usr/include /usr/include/KF5 $x_includes"
+    kf5_libdirs="$KF5LIB /usr/lib /usr/lib/kf5 /usr/lib/kf5/devel $x_libraries"
+
+    if test -n "$supports_multilib"; then
+        qt5_libdirs="$qt5_libdirs /usr/lib64/qt5 /usr/lib64/qt /usr/lib64"
+        kf5_libdirs="$kf5_libdirs /usr/lib64 /usr/lib64/kf5 /usr/lib64/kf5/devel"
+    fi
+
+    qt5_test_include="QtWidgets/qapplication.h"
+    qt5_test_library="libQt5Widgets.so"
+    kf5_test_include="kcoreaddons_version.h"
+    kf5_test_library="libKF5CoreAddons.so"
+
+    dnl Check for qmake
+    AC_PATH_PROGS( QMAKE5, [qmake-qt5 qmake], no, [$QT5DIR/bin:$PATH] )
+    if test "$QMAKE5" != "no"; then
+        qt5_incdirs="`$QMAKE5 -query QT_INSTALL_HEADERS` $qt5_incdirs"
+        qt5_libdirs="`$QMAKE5 -query QT_INSTALL_LIBS` $qt5_libdirs"
+    fi
+
+    AC_MSG_CHECKING([for Qt5 headers])
+    qt5_incdir="no"
+    for inc_dir in $qt5_incdirs; do
+        if test -r "$inc_dir/$qt5_test_include"; then
+            qt5_incdir="$inc_dir"
+            break
+        fi
+    done
+    AC_MSG_RESULT([$qt5_incdir])
+    if test "x$qt5_incdir" = "xno"; then
+        AC_MSG_ERROR([Qt5 headers not found.  Please specify the root of your Qt5 installation by exporting QT5DIR before running "configure".])
+    fi
+
+    AC_MSG_CHECKING([for Qt5 libraries])
+    qt5_libdir="no"
+    for lib_dir in $qt5_libdirs; do
+        if test -r "$lib_dir/$qt5_test_library"; then
+            qt5_libdir="$lib_dir"
+            break
+        fi
+    done
+    AC_MSG_RESULT([$qt5_libdir])
+    if test "x$qt5_libdir" = "xno"; then
+        AC_MSG_ERROR([Qt5 libraries not found.  Please specify the root of your Qt5 installation by exporting QT5DIR before running "configure".])
+    fi
+    kf5_libdirs="$qt5_libdir $kf5_libdirs"
+
+    dnl Check for Meta Object Compiler
+
+    AC_PATH_PROGS( MOC5, [moc-qt5 moc], no, [`dirname $qt5_libdir`/bin:$QT5DIR/bin:$PATH] )
+    if test "$MOC5" = "no"; then
+        AC_MSG_ERROR([Qt Meta Object Compiler not found.  Please specify
+the root of your Qt installation by exporting QT5DIR before running "configure".])
+    fi
+
+    dnl kf5 KDE4 support compatibility installed
+    AC_PATH_PROG( KF5_CONFIG, $KF5_CONFIG, no, )
+    if test "$KF5_CONFIG" != "no"; then
+        kf5_incdirs="`$KF5_CONFIG --path include` $kf5_incdirs"
+        kf5_libdirs="`$KF5_CONFIG --path lib` $kf5_libdirs"
+    fi
+
+    dnl Check for KF5 headers
+    AC_MSG_CHECKING([for KF5 headers])
+    kf5_incdir="no"
+    for kf5_check in $kf5_incdirs; do
+        if test -r "$kf5_check/$kf5_test_include"; then
+            kf5_incdir="$kf5_check"
+            break
+        fi
+    done
+    AC_MSG_RESULT([$kf5_incdir])
+    if test "x$kf5_incdir" = "xno"; then
+        AC_MSG_ERROR([KF5 headers not found.  Please specify the root of your KF5 installation by exporting KF5DIR before running "configure".])
+    fi
+
+    dnl Check for KF5 libraries
+    AC_MSG_CHECKING([for KF5 libraries])
+    kf5_libdir="no"
+    for kf5_check in $kf5_libdirs; do
+        if test -r "$kf5_check/$kf5_test_library"; then
+            kf5_libdir="$kf5_check"
+            break
+        fi
+    done
+
+    AC_MSG_RESULT([$kf5_libdir])
+    if test "x$kf5_libdir" = "xno"; then
+        AC_MSG_ERROR([KF5 libraries not found.  Please specify the root of your KF5 installation by exporting KF5DIR before running "configure".])
+    fi
+
+    PKG_CHECK_MODULES(KF5_XCB,[xcb],,[AC_MSG_ERROR([XCB not installed])])
+
+    KF5_CFLAGS="-I$kf5_incdir -I$kf5_incdir/KCoreAddons -I$kf5_incdir/KI18n -I$kf5_incdir/KConfigCore -I$kf5_incdir/KWindowSystem -I$kf5_incdir/KIOCore -I$qt5_incdir -I$qt5_incdir/QtCore -I$qt5_incdir/QtGui -I$qt5_incdir/QtWidgets -I$qt5_incdir/QtNetwork -DQT_CLEAN_NAMESPACE -DQT_THREAD_SUPPORT $KF5_XCB_CFLAGS"
+    KF5_LIBS="-L$kf5_libdir -lKF5CoreAddons -lKF5I18n -lKF5ConfigCore -lKF5WindowSystem -lKF5KIOCore -L$qt5_libdir -lQt5Core -lQt5Gui -lQt5Widgets -lQt5Network -lQt5X11Extras $KF5_XCB_LIBS"
+    KF5_CFLAGS=$(printf '%s' "$KF5_CFLAGS" | sed -e "s/-I/${ISYSTEM?}/g")
+
+    AC_LANG_PUSH([C++])
+    save_CXXFLAGS=$CXXFLAGS
+    CXXFLAGS="$CXXFLAGS $KF5_CFLAGS"
+    AC_MSG_CHECKING([whether KDE is >= 5.0])
+       AC_RUN_IFELSE([AC_LANG_SOURCE([[
+#include <kcoreaddons_version.h>
+
+int main(int argc, char **argv) {
+       if (KCOREADDONS_VERSION_MAJOR == 5 && KCOREADDONS_VERSION_MINOR >= 0) return 0;
+       else return 1;
+}
+       ]])],[AC_MSG_RESULT([yes])],[AC_MSG_ERROR([KDE version too old])],[])
+    CXXFLAGS=$save_CXXFLAGS
+    AC_LANG_POP([C++])
+
+    # Glib is needed for properly handling Qt event loop with Qt's Glib integration enabled.
+    # Sets also KF5_GLIB_CFLAGS/KF5_GLIB_LIBS if successful.
+    PKG_CHECK_MODULES(KF5_GLIB,[glib-2.0 >= 2.4],
+        [
+            KF5_HAVE_GLIB=1
+            AC_DEFINE(KF5_HAVE_GLIB,1)
+            KF5_GLIB_CFLAGS=$(printf '%s' "$KF5_GLIB_CFLAGS" | sed -e "s/-I/${ISYSTEM?}/g")
+            FilterLibs "${KF5_GLIB_LIBS}"
+            KF5_GLIB_LIBS="${filteredlibs}"
+
+            qt4_fix_warning=
+
+            AC_LANG_PUSH([C++])
+            # tst_exclude_socket_notifiers.moc:70:28: runtime error: member access within address 0x60d00000bb20 which does not point to an object of type 'QObjectData'
+            # 0x60d00000bb20: note: object is of type 'QObjectPrivate'
+            #  02 00 80 3a  90 8a 4e d2 3a 00 00 00  f0 b4 b9 a7 ff 7f 00 00  00 00 00 00 00 00 00 00  20 d8 4e d2
+            #               ^~~~~~~~~~~~~~~~~~~~~~~
+            #               vptr for 'QObjectPrivate'
+            save_CXX=$CXX
+            CXX=$(printf %s "$CXX" \
+                | sed -e 's/-fno-sanitize-recover\(=[[0-9A-Za-z,_-]]*\)*//')
+            save_CXXFLAGS=$CXXFLAGS
+            CXXFLAGS="$CXXFLAGS $KF5_CFLAGS"
+            save_LIBS=$LIBS
+            LIBS="$LIBS $KF5_LIBS"
+            AC_MSG_CHECKING([whether Qt has fixed ExcludeSocketNotifiers])
+
+            # Prepare meta object data
+            TSTBASE="tst_exclude_socket_notifiers"
+            TSTMOC="${SRC_ROOT}/vcl/unx/kde5/${TSTBASE}"
+            ln -fs "${TSTMOC}.hxx"
+            $MOC5 "${TSTBASE}.hxx" -o "${TSTBASE}.moc"
+
+            AC_RUN_IFELSE([AC_LANG_SOURCE([[
+#include <cstdlib>
+#include "tst_exclude_socket_notifiers.moc"
+
+int main(int argc, char *argv[])
+{
+    QCoreApplication app(argc, argv);
+    exit(tst_processEventsExcludeSocket());
+    return 0;
+}
+            ]])],[
+                AC_MSG_RESULT([yes])
+            ],[
+                AC_MSG_RESULT([no])
+                AC_MSG_WARN([native KF5 file pickers will be disabled at runtime])
+                if test -z "$qt5_fix_warning"; then
+                    add_warning "native KF5 file pickers will be disabled at runtime, Qt5 fixes needed"
+                fi
+                qt5_fix_warning=1
+                add_warning "  https://bugreports.qt-project.org/browse/QTBUG-37380 (needed)"
+            ])
+
+            # Remove meta object data
+            rm -f "${TSTBASE}."*
+
+            AC_MSG_CHECKING([whether Qt avoids QClipboard recursion caused by posted events])
+
+            # Prepare meta object data
+            TSTBASE="tst_exclude_posted_events"
+            TSTMOC="${SRC_ROOT}/vcl/unx/kde5/${TSTBASE}"
+            ln -fs "${TSTMOC}.hxx"
+            $MOC5 "${TSTBASE}.hxx" -o "${TSTBASE}.moc"
+
+            AC_RUN_IFELSE([AC_LANG_SOURCE([[
+#include <cstdlib>
+#include "tst_exclude_posted_events.moc"
+
+int main(int argc, char *argv[])
+{
+    QCoreApplication app(argc, argv);
+    exit(tst_excludePostedEvents());
+    return 0;
+}
+            ]])],[
+                AC_MSG_RESULT([yes])
+            ],[
+                AC_MSG_RESULT([no])
+                AC_MSG_WARN([native KF5 file pickers will be disabled at runtime])
+                if test -z "$qt5_fix_warning"; then
+                    add_warning "native KF5 file pickers will be disabled at runtime, Qt5 fixes needed"
+                fi
+                qt5_fix_warning=1
+                add_warning "  https://bugreports.qt-project.org/browse/QTBUG-34614 (needed)"
+            ])
+
+            # Remove meta object data
+            rm -f "${TSTBASE}."*
+
+            if test -n "$qt5_fix_warning"; then
+                add_warning "  https://bugreports.qt-project.org/browse/QTBUG-38585 (recommended)"
+            fi
+
+            LIBS=$save_LIBS
+            CXXFLAGS=$save_CXXFLAGS
+            CXX=$save_CXX
+            AC_LANG_POP([C++])
+        ],
+        AC_MSG_WARN([[No Glib found, KF5 support will not use native file pickers!]]))
+fi
+AC_SUBST(KF5_CFLAGS)
+AC_SUBST(KF5_LIBS)
+AC_SUBST(MOC5)
+AC_SUBST(KF5_GLIB_CFLAGS)
+AC_SUBST(KF5_GLIB_LIBS)
+AC_SUBST(KF5_HAVE_GLIB)
+
+dnl ===================================================================
 dnl Test whether to include Evolution 2 support
 dnl ===================================================================
 AC_MSG_CHECKING([whether to enable evolution 2 support])
@@ -12908,6 +13165,7 @@ AC_CONFIG_HEADERS([config_host/config_locales.h])
 AC_CONFIG_HEADERS([config_host/config_mpl.h])
 AC_CONFIG_HEADERS([config_host/config_orcus.h])
 AC_CONFIG_HEADERS([config_host/config_kde4.h])
+AC_CONFIG_HEADERS([config_host/config_kde5.h])
 AC_CONFIG_HEADERS([config_host/config_oox.h])
 AC_CONFIG_HEADERS([config_host/config_opengl.h])
 AC_CONFIG_HEADERS([config_host/config_options.h])
diff --git a/cui/Library_cui.mk b/cui/Library_cui.mk
index 86cc379..55cc9b2 100644
--- a/cui/Library_cui.mk
+++ b/cui/Library_cui.mk
@@ -22,6 +22,7 @@ $(eval $(call gb_Library_add_defs,cui,\
     $(if $(filter TRUE,$(ENABLE_GTK)),-DENABLE_GTK) \
     $(if $(filter TRUE,$(ENABLE_TDE)),-DENABLE_TDE) \
     $(if $(filter TRUE,$(ENABLE_KDE4)),-DENABLE_KDE4) \
+    $(if $(filter TRUE,$(ENABLE_KDE5)),-DENABLE_KDE5) \
 ))
 
 $(eval $(call gb_Library_use_custom_headers,cui,\
diff --git a/cui/source/options/optgdlg.cxx b/cui/source/options/optgdlg.cxx
index 52fc00c..b603c94 100644
--- a/cui/source/options/optgdlg.cxx
+++ b/cui/source/options/optgdlg.cxx
@@ -198,7 +198,15 @@ namespace
         {
             const OUString &rDesktopEnvironment = Application::GetDesktopEnvironment();
 
-            if ( rDesktopEnvironment.equalsIgnoreAsciiCase("kde4") )
+            if ( rDesktopEnvironment.equalsIgnoreAsciiCase("kde5") )
+            {
+                #if ENABLE_KDE5
+                return OUString("com.sun.star.ui.dialogs.KDE5FilePicker" );
+                #else
+                return OUString();
+                #endif
+            }
+            else if ( rDesktopEnvironment.equalsIgnoreAsciiCase("kde4") )
             {
                 #if ENABLE_KDE4
                 return OUString("com.sun.star.ui.dialogs.KDE4FilePicker" );
diff --git a/scp2/InstallScript_setup_osl.mk b/scp2/InstallScript_setup_osl.mk
index 593b1af..ca9f4cf 100644
--- a/scp2/InstallScript_setup_osl.mk
+++ b/scp2/InstallScript_setup_osl.mk
@@ -36,7 +36,7 @@ $(eval $(call gb_InstallScript_use_modules,setup_osl,\
 	$(if $(filter TRUE,$(ENABLE_EVOAB2) $(ENABLE_GIO) $(ENABLE_GTK) $(ENABLE_GTK3)),\
 		scp2/gnome \
 	) \
-	$(if $(filter TRUE,$(ENABLE_KDE4)),\
+	$(if $(filter TRUE,$(ENABLE_KDE4) $(ENABLE_KDE5)),\
 		scp2/kde \
 	) \
 	$(if $(filter TRUE,$(ENABLE_ONLINE_UPDATE)),\
diff --git a/scp2/Module_scp2.mk b/scp2/Module_scp2.mk
index 5acaa0c..6320483 100644
--- a/scp2/Module_scp2.mk
+++ b/scp2/Module_scp2.mk
@@ -42,7 +42,7 @@ $(eval $(call gb_Module_add_targets,scp2,\
 	$(if $(filter TRUE,$(ENABLE_EVOAB2) $(ENABLE_GIO) $(ENABLE_GTK) $(ENABLE_GTK3)),\
 		InstallModule_gnome \
 	) \
-	$(if $(filter TRUE,$(ENABLE_KDE4)),\
+	$(if $(filter TRUE,$(ENABLE_KDE4) $(ENABLE_KDE5)),\
 		InstallModule_kde \
 	) \
 	$(if $(filter TRUE,$(ENABLE_TDE)),\
diff --git a/shell/Library_kde5be.mk b/shell/Library_kde5be.mk
new file mode 100644
index 0000000..b9c7c90
--- /dev/null
+++ b/shell/Library_kde5be.mk
@@ -0,0 +1,32 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_Library_Library,kde5be1))
+
+$(eval $(call gb_Library_use_sdk_api,kde5be1))
+
+$(eval $(call gb_Library_use_externals,kde5be1,\
+	boost_headers \
+	kde5 \
+))
+
+$(eval $(call gb_Library_use_libraries,kde5be1,\
+	cppu \
+	cppuhelper \
+	sal \
+))
+
+$(eval $(call gb_Library_set_componentfile,kde5be1,shell/source/backends/kde5be/kde5be1))
+
+$(eval $(call gb_Library_add_exception_objects,kde5be1,\
+    shell/source/backends/kde5be/kde5access \
+    shell/source/backends/kde5be/kde5backend \
+))
+
+# vim: set shiftwidth=4 tabstop=4 noexpandtab:
diff --git a/shell/Module_shell.mk b/shell/Module_shell.mk
index d0a3318..d0c1925 100644
--- a/shell/Module_shell.mk
+++ b/shell/Module_shell.mk
@@ -36,6 +36,12 @@ $(eval $(call gb_Module_add_targets,shell,\
 ))
 endif
 
+ifeq ($(ENABLE_KDE5),TRUE)
+$(eval $(call gb_Module_add_targets,shell,\
+	Library_kde5be \
+))
+endif
+
 ifeq ($(ENABLE_TDE),TRUE)
 $(eval $(call gb_Module_add_targets,shell,\
 	Library_tdebe \
diff --git a/shell/source/backends/kde4be/kde4access.cxx b/shell/source/backends/kde4be/kde4access.cxx
index 5d962b7..b67d5aa 100644
--- a/shell/source/backends/kde4be/kde4access.cxx
+++ b/shell/source/backends/kde4be/kde4access.cxx
@@ -19,6 +19,8 @@
 
 #include "sal/config.h"
 
+#include "kde4access.hxx"
+
 #include <QtGui/QFont>
 #include <QtCore/QString>
 #include <kemailsettings.h>
@@ -32,8 +34,6 @@
 #include "rtl/string.h"
 #include "rtl/ustring.hxx"
 
-#include "kde4access.hxx"
-
 #define SPACE      ' '
 #define COMMA      ','
 #define SEMI_COLON ';'
diff --git a/shell/source/backends/kde5be/kde5access.cxx b/shell/source/backends/kde5be/kde5access.cxx
new file mode 100644
index 0000000..a6391eb
--- /dev/null
+++ b/shell/source/backends/kde5be/kde5access.cxx
@@ -0,0 +1,309 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "sal/config.h"
+
+#include "kde5access.hxx"
+
+#include <QtGui/QFont>
+#include <QtCore/QString>
+#include <QtGui/QFontDatabase>
+#include <QtCore/QStandardPaths>
+#include <QtCore/QDir>
+#include <QtCore/QUrl>
+
+#include <kprotocolmanager.h>
+
+#include <kemailsettings.h>
+// #include <kglobalsettings.h>
+// #include <kprotocolmanager.h>
+
+#include "com/sun/star/uno/Any.hxx"
+#include "cppu/unotype.hxx"
+#include "osl/diagnose.h"
+#include "osl/file.h"
+#include "rtl/string.h"
+#include "rtl/ustring.hxx"
+
+#define SPACE      ' '
+#define COMMA      ','
+#define SEMI_COLON ';'
+
+namespace kde5access {
+
+namespace {
+
+namespace uno = css::uno ;
+
+}
+
+css::beans::Optional< css::uno::Any > getValue(OUString const & id) {
+    if ( id == "ExternalMailer" ) {
+        KEMailSettings aEmailSettings;
+        QString aClientProgram;
+        OUString sClientProgram;
+
+        aClientProgram = aEmailSettings.getSetting( KEMailSettings::ClientProgram );
+        if ( aClientProgram.isEmpty() )
+            aClientProgram = "kmail";
+        else
+            aClientProgram = aClientProgram.section(SPACE, 0, 0);
+        sClientProgram = reinterpret_cast<const sal_Unicode *>(aClientProgram.utf16());
+        return css::beans::Optional< css::uno::Any >(
+            true, uno::makeAny( sClientProgram ) );
+    } else if (id == "SourceViewFontHeight")
+    {
+        QFont aFixedFont;
+        short nFontHeight;
+
+        aFixedFont = QFontDatabase::systemFont(QFontDatabase::FixedFont);
+        nFontHeight = aFixedFont.pointSize();
+        return css::beans::Optional< css::uno::Any >(
+            true, uno::makeAny( nFontHeight ) );
+    } else if (id == "SourceViewFontName")
+    {
+        QFont aFixedFont;
+        QString aFontName;
+        OUString sFontName;
+
+        aFixedFont = QFontDatabase::systemFont(QFontDatabase::FixedFont);
+        aFontName = aFixedFont.family();
+        sFontName = reinterpret_cast<const sal_Unicode *>(aFontName.utf16());
+        return css::beans::Optional< css::uno::Any >(
+            true, uno::makeAny( sFontName ) );
+    } else if (id == "EnableATToolSupport")
+    {
+        /* does not make much sense without an accessibility bridge */
+        bool ATToolSupport = false;
+        return css::beans::Optional< css::uno::Any >(
+            true, uno::makeAny( OUString::boolean( ATToolSupport ) ) );
+    } else if (id == "WorkPathVariable")
+    {
+        QString aDocumentsDir( QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation) );
+        if (aDocumentsDir.isEmpty() ) aDocumentsDir = QDir::homePath();
+        OUString sDocumentsDir;
+        OUString sDocumentsURL;
+        if ( aDocumentsDir.endsWith(QChar('/')) )
+            aDocumentsDir.truncate ( aDocumentsDir.length() - 1 );
+        sDocumentsDir = reinterpret_cast<const sal_Unicode *>(aDocumentsDir.utf16());
+        osl_getFileURLFromSystemPath( sDocumentsDir.pData, &sDocumentsURL.pData );
+        return css::beans::Optional< css::uno::Any >(
+            true, uno::makeAny( sDocumentsURL ) );
+    } else if (id == "ooInetFTPProxyName")
+    {
+        QString aFTPProxy;
+        switch ( KProtocolManager::proxyType() )
+        {
+        case KProtocolManager::ManualProxy: // Proxies are manually configured
+            aFTPProxy = KProtocolManager::proxyFor( "FTP" );
+            break;
+        case KProtocolManager::PACProxy:    // A proxy configuration URL has been given
+        case KProtocolManager::WPADProxy:   // A proxy should be automatically discovered
+        case KProtocolManager::EnvVarProxy: // Use the proxy values set through environment variables
+// In such cases, the proxy address is not stored in KDE, but determined dynamically.
+// The proxy address may depend on the requested address, on the time of the day, on the speed of the wind...
+// The best we can do here is to ask the current value for a given address.
+            aFTPProxy = KProtocolManager::proxyForUrl( QUrl("ftp://ftp.libreoffice.org") );
+            break;
+        default:                            // No proxy is used
+            break;
+        }
+        if ( !aFTPProxy.isEmpty() )
+        {
+            QUrl aProxy(aFTPProxy);
+            OUString sProxy = reinterpret_cast<const sal_Unicode *>(aProxy.host().utf16());
+            return css::beans::Optional< css::uno::Any >(
+                true, uno::makeAny( sProxy ) );
+        }
+    } else if (id == "ooInetFTPProxyPort")
+    {
+        QString aFTPProxy;
+        switch ( KProtocolManager::proxyType() )
+        {
+        case KProtocolManager::ManualProxy: // Proxies are manually configured
+            aFTPProxy = KProtocolManager::proxyFor( "FTP" );
+            break;
+        case KProtocolManager::PACProxy:    // A proxy configuration URL has been given
+        case KProtocolManager::WPADProxy:   // A proxy should be automatically discovered
+        case KProtocolManager::EnvVarProxy: // Use the proxy values set through environment variables
+// In such cases, the proxy address is not stored in KDE, but determined dynamically.
+// The proxy address may depend on the requested address, on the time of the day, on the speed of the wind...
+// The best we can do here is to ask the current value for a given address.
+            aFTPProxy = KProtocolManager::proxyForUrl( QUrl("ftp://ftp.libreoffice.org") );
+            break;
+        default:                            // No proxy is used
+            break;
+        }
+        if ( !aFTPProxy.isEmpty() )
+        {
+            QUrl aProxy(aFTPProxy);
+            sal_Int32 nPort = aProxy.port();
+            return css::beans::Optional< css::uno::Any >(
+                true, uno::makeAny( nPort ) );
+        }
+    } else if (id == "ooInetHTTPProxyName")
+    {
+        QString aHTTPProxy;
+        switch ( KProtocolManager::proxyType() )
+        {
+        case KProtocolManager::ManualProxy: // Proxies are manually configured
+            aHTTPProxy = KProtocolManager::proxyFor( "HTTP" );
+            break;
+        case KProtocolManager::PACProxy:    // A proxy configuration URL has been given
+        case KProtocolManager::WPADProxy:   // A proxy should be automatically discovered
+        case KProtocolManager::EnvVarProxy: // Use the proxy values set through environment variables
+// In such cases, the proxy address is not stored in KDE, but determined dynamically.
+// The proxy address may depend on the requested address, on the time of the day, on the speed of the wind...
+// The best we can do here is to ask the current value for a given address.
+            aHTTPProxy = KProtocolManager::proxyForUrl( QUrl("http://http.libreoffice.org") );
+            break;
+        default:                            // No proxy is used
+            break;
+        }
+        if ( !aHTTPProxy.isEmpty() )
+        {
+            QUrl aProxy(aHTTPProxy);
+            OUString sProxy = reinterpret_cast<const sal_Unicode *>(aProxy.host().utf16());
+            return css::beans::Optional< css::uno::Any >(
+                true, uno::makeAny( sProxy ) );
+        }
+    } else if (id == "ooInetHTTPProxyPort")
+    {
+        QString aHTTPProxy;
+        switch ( KProtocolManager::proxyType() )
+        {
+        case KProtocolManager::ManualProxy: // Proxies are manually configured
+            aHTTPProxy = KProtocolManager::proxyFor( "HTTP" );
+            break;
+        case KProtocolManager::PACProxy:    // A proxy configuration URL has been given
+        case KProtocolManager::WPADProxy:   // A proxy should be automatically discovered
+        case KProtocolManager::EnvVarProxy: // Use the proxy values set through environment variables
+// In such cases, the proxy address is not stored in KDE, but determined dynamically.
+// The proxy address may depend on the requested address, on the time of the day, on the speed of the wind...
+// The best we can do here is to ask the current value for a given address.
+            aHTTPProxy = KProtocolManager::proxyForUrl( QUrl("http://http.libreoffice.org") );
+            break;
+        default:                            // No proxy is used
+            break;
+        }
+        if ( !aHTTPProxy.isEmpty() )
+        {
+            QUrl aProxy(aHTTPProxy);
+            sal_Int32 nPort = aProxy.port();
+            return css::beans::Optional< css::uno::Any >(
+                true, uno::makeAny( nPort ) );
+        }
+    } else if (id == "ooInetHTTPSProxyName")
+    {
+        QString aHTTPSProxy;
+        switch ( KProtocolManager::proxyType() )
+        {
+        case KProtocolManager::ManualProxy: // Proxies are manually configured
+            aHTTPSProxy = KProtocolManager::proxyFor( "HTTPS" );
+            break;
+        case KProtocolManager::PACProxy:    // A proxy configuration URL has been given
+        case KProtocolManager::WPADProxy:   // A proxy should be automatically discovered
+        case KProtocolManager::EnvVarProxy: // Use the proxy values set through environment variables
+// In such cases, the proxy address is not stored in KDE, but determined dynamically.
+// The proxy address may depend on the requested address, on the time of the day, on the speed of the wind...
+// The best we can do here is to ask the current value for a given address.
+            aHTTPSProxy = KProtocolManager::proxyForUrl( QUrl("https://https.libreoffice.org") );
+            break;
+        default:                            // No proxy is used
+            break;
+        }
+        if ( !aHTTPSProxy.isEmpty() )
+        {
+            QUrl aProxy(aHTTPSProxy);
+            OUString sProxy = reinterpret_cast<const sal_Unicode *>(aProxy.host().utf16());
+            return css::beans::Optional< css::uno::Any >(
+                true, uno::makeAny( sProxy ) );
+        }
+    } else if (id == "ooInetHTTPSProxyPort")
+    {
+        QString aHTTPSProxy;
+        switch ( KProtocolManager::proxyType() )
+        {
+        case KProtocolManager::ManualProxy: // Proxies are manually configured
+            aHTTPSProxy = KProtocolManager::proxyFor( "HTTPS" );
+            break;
+        case KProtocolManager::PACProxy:    // A proxy configuration URL has been given
+        case KProtocolManager::WPADProxy:   // A proxy should be automatically discovered
+        case KProtocolManager::EnvVarProxy: // Use the proxy values set through environment variables
+// In such cases, the proxy address is not stored in KDE, but determined dynamically.
+// The proxy address may depend on the requested address, on the time of the day, on the speed of the wind...
+// The best we can do here is to ask the current value for a given address.
+            aHTTPSProxy = KProtocolManager::proxyForUrl( QUrl("https://https.libreoffice.org") );
+            break;
+        default:                            // No proxy is used
+            break;
+        }
+        if ( !aHTTPSProxy.isEmpty() )
+        {
+            QUrl aProxy(aHTTPSProxy);
+            sal_Int32 nPort = aProxy.port();
+            return css::beans::Optional< css::uno::Any >(
+                true, uno::makeAny( nPort ) );
+        }
+    } else if ( id == "ooInetNoProxy" ) {
+        QString aNoProxyFor;
+        switch ( KProtocolManager::proxyType() )
+        {
+        case KProtocolManager::ManualProxy: // Proxies are manually configured
+        case KProtocolManager::PACProxy:    // A proxy configuration URL has been given
+        case KProtocolManager::WPADProxy:   // A proxy should be automatically discovered
+        case KProtocolManager::EnvVarProxy: // Use the proxy values set through environment variables
+            aNoProxyFor = KProtocolManager::noProxyFor();
+            break;
+        default:                            // No proxy is used
+            break;
+        }
+        if ( !aNoProxyFor.isEmpty() )
+        {
+            OUString sNoProxyFor;
+
+            aNoProxyFor = aNoProxyFor.replace( COMMA, SEMI_COLON );
+            sNoProxyFor = reinterpret_cast<const sal_Unicode *>(aNoProxyFor.utf16());
+            return css::beans::Optional< css::uno::Any >(
+                true, uno::makeAny( sNoProxyFor ) );
+        }
+    } else if ( id == "ooInetProxyType" ) {
+        int nProxyType;
+        switch ( KProtocolManager::proxyType() )
+        {
+        case KProtocolManager::ManualProxy: // Proxies are manually configured
+        case KProtocolManager::PACProxy:    // A proxy configuration URL has been given
+        case KProtocolManager::WPADProxy:   // A proxy should be automatically discovered
+        case KProtocolManager::EnvVarProxy: // Use the proxy values set through environment variables
+            nProxyType = 1;
+            break;
+        default:                            // No proxy is used
+            nProxyType = 0;
+        }
+        return css::beans::Optional< css::uno::Any >(
+            true, uno::makeAny( (sal_Int32) nProxyType ) );
+    } else {
+        OSL_ASSERT(false); // this cannot happen
+    }
+    return css::beans::Optional< css::uno::Any >();
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/shell/source/backends/kde5be/kde5access.hxx b/shell/source/backends/kde5be/kde5access.hxx
new file mode 100644
index 0000000..fbb4a3b
--- /dev/null
+++ b/shell/source/backends/kde5be/kde5access.hxx
@@ -0,0 +1,39 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_SHELL_SOURCE_BACKENDS_KDE5BE_KDE5ACCESS_HXX
+#define INCLUDED_SHELL_SOURCE_BACKENDS_KDE5BE_KDE5ACCESS_HXX
+
+#include "sal/config.h"
+
+#include "com/sun/star/beans/Optional.hpp"
+
+namespace com { namespace sun { namespace star { namespace uno {
+    class Any;
+} } } }
+
+namespace kde5access {
+
+css::beans::Optional< css::uno::Any > getValue(OUString const & id);
+
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/shell/source/backends/kde5be/kde5backend.cxx b/shell/source/backends/kde5be/kde5backend.cxx
new file mode 100644
index 0000000..a32dbc1
--- /dev/null
+++ b/shell/source/backends/kde5be/kde5backend.cxx
@@ -0,0 +1,209 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "sal/config.h"
+
+#include <QtWidgets/QApplication>
+
+#include "boost/noncopyable.hpp"
+#include "com/sun/star/beans/Optional.hpp"
+#include "com/sun/star/beans/PropertyVetoException.hpp"
+#include "com/sun/star/beans/UnknownPropertyException.hpp"
+#include "com/sun/star/beans/XPropertyChangeListener.hpp"
+#include "com/sun/star/beans/XPropertySet.hpp"
+#include "com/sun/star/beans/XPropertySetInfo.hpp"
+#include "com/sun/star/beans/XVetoableChangeListener.hpp"
+#include "com/sun/star/lang/IllegalArgumentException.hpp"
+#include "com/sun/star/lang/WrappedTargetException.hpp"
+#include "com/sun/star/lang/XMultiComponentFactory.hpp"
+#include "com/sun/star/lang/XServiceInfo.hpp"
+#include "com/sun/star/uno/Any.hxx"
+#include "com/sun/star/uno/Reference.hxx"
+#include "com/sun/star/uno/RuntimeException.hpp"
+#include "com/sun/star/uno/Sequence.hxx"
+#include "com/sun/star/uno/XComponentContext.hpp"
+#include "com/sun/star/uno/XCurrentContext.hpp"
+#include "cppuhelper/factory.hxx"
+#include <cppuhelper/implbase.hxx>
+#include "cppuhelper/implementationentry.hxx"
+#include "cppuhelper/weak.hxx"
+#include "rtl/string.h"
+#include "rtl/ustring.h"
+#include "rtl/ustring.hxx"
+#include "sal/types.h"
+#include "uno/current_context.hxx"
+
+#include "kde5access.hxx"
+
+namespace {
+
+OUString SAL_CALL getServiceImplementationName() {
+    return OUString(
+            "com.sun.star.comp.configuration.backend.KDE5Backend");
+}
+
+css::uno::Sequence< OUString > SAL_CALL getServiceSupportedServiceNames() {
+    OUString name(
+            "com.sun.star.configuration.backend.KDE5Backend");
+    return css::uno::Sequence< OUString >(&name, 1);
+}
+
+class Service:
+    public cppu::WeakImplHelper<
+        css::lang::XServiceInfo, css::beans::XPropertySet >,
+    private boost::noncopyable
+{
+public:
+    Service();
+
+private:
+    virtual ~Service() {}
+
+    virtual OUString SAL_CALL getImplementationName()
+        throw (css::uno::RuntimeException, std::exception) override
+    { return getServiceImplementationName(); }
+
+    virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName)
+        throw (css::uno::RuntimeException, std::exception) override
+    { return ServiceName == getSupportedServiceNames()[0]; }
+
+    virtual css::uno::Sequence< OUString > SAL_CALL
+    getSupportedServiceNames() throw (css::uno::RuntimeException, std::exception) override
+    { return getServiceSupportedServiceNames(); }
+
+    virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL
+    getPropertySetInfo() throw (css::uno::RuntimeException, std::exception) override
+    { return css::uno::Reference< css::beans::XPropertySetInfo >(); }
+
+    virtual void SAL_CALL setPropertyValue(
+        OUString const &, css::uno::Any const &)
+        throw (
+            css::beans::UnknownPropertyException,
+            css::beans::PropertyVetoException,
+            css::lang::IllegalArgumentException,
+            css::lang::WrappedTargetException, css::uno::RuntimeException, std::exception) override;
+
+    virtual css::uno::Any SAL_CALL getPropertyValue(
+        OUString const & PropertyName)
+        throw (
+            css::beans::UnknownPropertyException,
+            css::lang::WrappedTargetException, css::uno::RuntimeException, std::exception) override;
+
+    virtual void SAL_CALL addPropertyChangeListener(
+        OUString const &,
+        css::uno::Reference< css::beans::XPropertyChangeListener > const &)
+        throw (
+            css::beans::UnknownPropertyException,
+            css::lang::WrappedTargetException, css::uno::RuntimeException, std::exception) override
+    {}
+
+    virtual void SAL_CALL removePropertyChangeListener(
+        OUString const &,
+        css::uno::Reference< css::beans::XPropertyChangeListener > const &)
+        throw (
+            css::beans::UnknownPropertyException,
+            css::lang::WrappedTargetException, css::uno::RuntimeException, std::exception) override
+    {}
+
+    virtual void SAL_CALL addVetoableChangeListener(
+        OUString const &,
+        css::uno::Reference< css::beans::XVetoableChangeListener > const &)
+        throw (
+            css::beans::UnknownPropertyException,
+            css::lang::WrappedTargetException, css::uno::RuntimeException, std::exception) override
+    {}
+
+    virtual void SAL_CALL removeVetoableChangeListener(
+        OUString const &,
+        css::uno::Reference< css::beans::XVetoableChangeListener > const &)
+        throw (
+            css::beans::UnknownPropertyException,
+            css::lang::WrappedTargetException, css::uno::RuntimeException, std::exception) override
+    {}
+
+    bool enabled_;
+};
+
+Service::Service(): enabled_(false) {
+    css::uno::Reference< css::uno::XCurrentContext > context(
+        css::uno::getCurrentContext());
+    if (context.is()) {
+        OUString desktop;
+        context->getValueByName("system.desktop-environment") >>= desktop;
+        enabled_ = desktop == "KDE5" && qApp != nullptr;
+    }
+}
+
+void Service::setPropertyValue(OUString const &, css::uno::Any const &)
+    throw (
+        css::beans::UnknownPropertyException, css::beans::PropertyVetoException,
+        css::lang::IllegalArgumentException, css::lang::WrappedTargetException,
+        css::uno::RuntimeException, std::exception)
+{
+    throw css::lang::IllegalArgumentException(
+        OUString("setPropertyValue not supported"),
+        static_cast< cppu::OWeakObject * >(this), -1);
+}
+
+css::uno::Any Service::getPropertyValue(OUString const & PropertyName)
+    throw (
+        css::beans::UnknownPropertyException, css::lang::WrappedTargetException,
+        css::uno::RuntimeException, std::exception)
+{
+    if (PropertyName == "EnableATToolSupport" || PropertyName == "ExternalMailer" || PropertyName == "SourceViewFontHeight"
+     || PropertyName == "SourceViewFontName" || PropertyName == "WorkPathVariable" || PropertyName == "ooInetFTPProxyName"
+     || PropertyName == "ooInetFTPProxyPort" || PropertyName == "ooInetHTTPProxyName" || PropertyName == "ooInetHTTPProxyPort"
+     || PropertyName == "ooInetHTTPSProxyName" || PropertyName == "ooInetHTTPSProxyPort" || PropertyName == "ooInetNoProxy"
+     || PropertyName == "ooInetProxyType" || PropertyName == "TemplatePathVariable" )
+    {
+        return css::uno::makeAny(
+            enabled_
+            ? kde5access::getValue(PropertyName)
+            : css::beans::Optional< css::uno::Any >());
+    } else if (PropertyName == "givenname" || PropertyName == "sn") {
+        return css::uno::makeAny(css::beans::Optional< css::uno::Any >());
+            //TODO: obtain values from KDE?
+    }
+    throw css::beans::UnknownPropertyException(
+        PropertyName, static_cast< cppu::OWeakObject * >(this));
+}
+
+css::uno::Reference< css::uno::XInterface > SAL_CALL createInstance(
+    css::uno::Reference< css::uno::XComponentContext > const &)
+{
+    return static_cast< cppu::OWeakObject * >(new Service);
+}
+
+static cppu::ImplementationEntry const services[] = {
+    { &createInstance, &getServiceImplementationName,
+      &getServiceSupportedServiceNames, &cppu::createSingleComponentFactory, nullptr,
+      0 },
+    { nullptr, nullptr, nullptr, nullptr, nullptr, 0 }
+};
+
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT void * SAL_CALL kde5be1_component_getFactory(
+    char const * pImplName, void * pServiceManager, void * pRegistryKey)
+{
+    return cppu::component_getFactoryHelper(
+        pImplName, pServiceManager, pRegistryKey, services);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/shell/source/backends/kde5be/kde5be1.component b/shell/source/backends/kde5be/kde5be1.component
new file mode 100644
index 0000000..7411187
--- /dev/null
+++ b/shell/source/backends/kde5be/kde5be1.component
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+
+<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@"
+    prefix="kde5be1" xmlns="http://openoffice.org/2010/uno-components">
+  <implementation name="com.sun.star.comp.configuration.backend.KDE5Backend">
+    <service name="com.sun.star.configuration.backend.KDE5Backend"/>
+  </implementation>
+</component>
diff --git a/solenv/gbuild/CppunitTest.mk b/solenv/gbuild/CppunitTest.mk
index b90fb7f..99924fb 100644
--- a/solenv/gbuild/CppunitTest.mk
+++ b/solenv/gbuild/CppunitTest.mk
@@ -182,6 +182,7 @@ $(call gb_CppunitTest_get_target,$(1)) : $(if $(filter $(2),$(true)),, \
         $(if $(ENABLE_GTK),$(call gb_Library_get_target,vclplug_gtk)) \
         $(if $(ENABLE_GTK3),$(call gb_Library_get_target,vclplug_gtk3)) \
         $(if $(ENABLE_KDE4),$(call gb_Library_get_target,vclplug_kde4)) \
+        $(if $(ENABLE_KDE5),$(call gb_Library_get_target,vclplug_kde5)) \
         $(if $(ENABLE_TDE),$(call gb_Library_get_target,vclplug_tde)))
 endif
 
diff --git a/sysui/CustomTarget_share.mk b/sysui/CustomTarget_share.mk
index c81edd5..8cc67e4 100644
--- a/sysui/CustomTarget_share.mk
+++ b/sysui/CustomTarget_share.mk
@@ -16,6 +16,8 @@ else ifeq ($(ENABLE_TDE),TRUE)
 	brand_URIPARAM := --urls
 else ifeq ($(ENABLE_KDE4),TRUE)
 	brand_URIPARAM := --urls
+else ifeq ($(ENABLE_KDE5),TRUE)
+	brand_URIPARAM := --urls
 else
 	brand_URIPARAM :=
 endif
diff --git a/vcl/CustomTarget_kde5_moc.mk b/vcl/CustomTarget_kde5_moc.mk
new file mode 100644
index 0000000..93810d9
--- /dev/null
+++ b/vcl/CustomTarget_kde5_moc.mk
@@ -0,0 +1,24 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_CustomTarget_CustomTarget,vcl/unx/kde5))
+
+$(call gb_CustomTarget_get_target,vcl/unx/kde5) : \
+	$(call gb_CustomTarget_get_workdir,vcl/unx/kde5)/KDEXLib.moc \
+	$(call gb_CustomTarget_get_workdir,vcl/unx/kde5)/KDE5FilePicker.moc \
+	$(call gb_CustomTarget_get_workdir,vcl/unx/kde5)/tst_exclude_socket_notifiers.moc \
+	$(call gb_CustomTarget_get_workdir,vcl/unx/kde5)/tst_exclude_posted_events.moc
+
+$(call gb_CustomTarget_get_workdir,vcl/unx/kde5)/%.moc : \
+		$(SRCDIR)/vcl/unx/kde5/%.hxx \
+		| $(call gb_CustomTarget_get_workdir,vcl/unx/kde5)/.dir
+	$(call gb_Output_announce,$(subst $(WORKDIR)/,,$@),$(true),MOC,1)
+	$(MOC5) $< -o $@
+
+# vim: set noet sw=4:
diff --git a/vcl/Library_vclplug_kde5.mk b/vcl/Library_vclplug_kde5.mk
new file mode 100644
index 0000000..b3d02fd
--- /dev/null
+++ b/vcl/Library_vclplug_kde5.mk
@@ -0,0 +1,98 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This file incorporates work covered by the following license notice:
+#
+#   Licensed to the Apache Software Foundation (ASF) under one or more
+#   contributor license agreements. See the NOTICE file distributed
+#   with this work for additional information regarding copyright
+#   ownership. The ASF licenses this file to you under the Apache
+#   License, Version 2.0 (the "License"); you may not use this file
+#   except in compliance with the License. You may obtain a copy of
+#   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+#
+
+$(eval $(call gb_Library_Library,vclplug_kde5))
+
+$(eval $(call gb_Library_use_custom_headers,vclplug_kde5,vcl/unx/kde5))
+
+$(eval $(call gb_Library_set_include,vclplug_kde5,\
+    $$(INCLUDE) \
+    -I$(SRCDIR)/vcl/inc \
+))
+
+$(eval $(call gb_Library_add_defs,vclplug_kde5,\
+    -DVCLPLUG_KDE5_IMPLEMENTATION \
+))
+
+$(eval $(call gb_Library_use_sdk_api,vclplug_kde5))
+
+$(eval $(call gb_Library_use_libraries,vclplug_kde5,\
+    vclplug_gen \
+    vcl \
+    tl \
+    utl \
+    sot \
+    ucbhelper \
+    basegfx \
+    comphelper \
+    cppuhelper \
+    i18nlangtag \
+    i18nutil \
+    $(if $(ENABLE_JAVA), \
+        jvmaccess) \
+    cppu \
+    sal \
+))
+
+$(eval $(call gb_Library_use_externals,vclplug_kde5,\
+	boost_headers \
+	icuuc \
+	kde5 \
+	glew \
+))
+
+$(eval $(call gb_Library_add_libs,vclplug_kde5,\
+	-lX11 \
+	-lXext \
+	-lSM \
+	-lICE \
+))
+
+ifneq ($(KF5_HAVE_GLIB),)
+$(eval $(call gb_Library_add_defs,vclplug_kde5,\
+    $(KF5_GLIB_CFLAGS) \
+))
+
+$(eval $(call gb_Library_add_libs,vclplug_kde5,\
+    $(KF5_GLIB_LIBS) \
+))
+endif
+
+
+$(eval $(call gb_Library_add_exception_objects,vclplug_kde5,\
+    vcl/unx/kde5/KDEData \
+    vcl/unx/kde5/KDE5FilePicker \
+    vcl/unx/kde5/KDESalDisplay \
+    vcl/unx/kde5/KDESalFrame \
+    vcl/unx/kde5/KDESalGraphics \
+    vcl/unx/kde5/KDESalInstance \
+    vcl/unx/kde5/KDEXLib \
+    vcl/unx/kde5/main \
+    vcl/unx/kde5/VCLKDEApplication \
+))
+
+ifeq ($(OS),LINUX)
+$(eval $(call gb_Library_add_libs,vclplug_kde5,\
+	-lm \
+	-ldl \
+	-lpthread \
+))
+endif
+
+# vim: set noet sw=4 ts=4:
diff --git a/vcl/Module_vcl.mk b/vcl/Module_vcl.mk
index 1480504..82c076e 100644
--- a/vcl/Module_vcl.mk
+++ b/vcl/Module_vcl.mk
@@ -79,6 +79,12 @@ $(eval $(call gb_Module_add_targets,vcl,\
     Library_vclplug_kde4 \
 ))
 endif
+ifneq ($(ENABLE_KDE5),)
+$(eval $(call gb_Module_add_targets,vcl,\
+    CustomTarget_kde5_moc \
+    Library_vclplug_kde5 \
+))
+endif
 endif
 
 ifeq ($(OS),MACOSX)
diff --git a/vcl/inc/generic/gendata.hxx b/vcl/inc/generic/gendata.hxx
index b2223b5..1a843e3 100644
--- a/vcl/inc/generic/gendata.hxx
+++ b/vcl/inc/generic/gendata.hxx
@@ -20,7 +20,7 @@ enum SalGenericDataType { SAL_DATA_GTK, SAL_DATA_GTK3,
                           SAL_DATA_TDE3, SAL_DATA_KDE3, SAL_DATA_KDE4,
                           SAL_DATA_UNX, SAL_DATA_SVP,
                           SAL_DATA_ANDROID, SAL_DATA_IOS,
-                          SAL_DATA_HEADLESS };
+                          SAL_DATA_HEADLESS, SAL_DATA_KDE5 };
 
 class VCL_DLLPUBLIC SalGenericData : public SalData
 {
diff --git a/vcl/inc/vclpluginapi.h b/vcl/inc/vclpluginapi.h
index 86fbf17..d274b0b 100644
--- a/vcl/inc/vclpluginapi.h
+++ b/vcl/inc/vclpluginapi.h
@@ -53,6 +53,12 @@
 #define VCLPLUG_KDE4_PUBLIC SAL_DLLPUBLIC_IMPORT
 #endif
 
+#if defined VCLPLUG_KDE5_IMPLEMENTATION
+#define VCLPLUG_KDE5_PUBLIC SAL_DLLPUBLIC_EXPORT
+#else
+#define VCLPLUG_KDE5_PUBLIC SAL_DLLPUBLIC_IMPORT
+#endif
+
 #if defined VCLPLUG_SVP_IMPLEMENTATION
 #define VCLPLUG_SVP_PUBLIC SAL_DLLPUBLIC_EXPORT
 #else
diff --git a/vcl/unx/generic/plugadapt/salplug.cxx b/vcl/unx/generic/plugadapt/salplug.cxx
index c51d1ec..78d1fb6 100644
--- a/vcl/unx/generic/plugadapt/salplug.cxx
+++ b/vcl/unx/generic/plugadapt/salplug.cxx
@@ -99,7 +99,7 @@ static SalInstance* tryInstance( const OUString& rModuleBase, bool bForce = fals
                  * #i109007# KDE3 seems to have the same problem.
                  * And same applies for KDE4.
                  */
-                if( rModuleBase == "gtk" || rModuleBase == "gtk3" || rModuleBase == "tde" || rModuleBase == "kde" || rModuleBase == "kde4" )
+                if( rModuleBase == "gtk" || rModuleBase == "gtk3" || rModuleBase == "tde" || rModuleBase == "kde" || rModuleBase == "kde4" || rModuleBase == "kde5" )
                 {
                     pCloseModule = nullptr;
                 }
@@ -168,6 +168,9 @@ static SalInstance* autodetect_plugin()
     static const char* const pTDEFallbackList[] =
     {
         "tde",
+#if ENABLE_KDE5 && 0
+        "kde5",
+#endif
 #if ENABLE_KDE4
         "kde4",
 #endif
@@ -176,6 +179,9 @@ static SalInstance* autodetect_plugin()
 
     static const char* const pKDEFallbackList[] =
     {
+#if ENABLE_KDE5 && 0
+        "kde5",
+#endif
 #if ENABLE_KDE4
         "kde4",
 #endif
diff --git a/vcl/unx/kde5/FPServiceInfo.hxx b/vcl/unx/kde5/FPServiceInfo.hxx
new file mode 100644
index 0000000..7c67a3b
--- /dev/null
+++ b/vcl/unx/kde5/FPServiceInfo.hxx
@@ -0,0 +1,28 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+// the service names
+#define FILE_PICKER_SERVICE_NAME "com.sun.star.ui.dialogs.KDE5FilePicker"
+
+// the implementation names
+#define FILE_PICKER_IMPL_NAME    "com.sun.star.ui.dialogs.KDE5FilePicker"
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/kde5/KDE5FilePicker.cxx b/vcl/unx/kde5/KDE5FilePicker.cxx
new file mode 100644
index 0000000..1c32c3e
--- /dev/null
+++ b/vcl/unx/kde5/KDE5FilePicker.cxx
@@ -0,0 +1,816 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "KDE5FilePicker.hxx"
+
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <cppuhelper/interfacecontainer.h>
+#include <cppuhelper/supportsservice.hxx>
+#include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
+#include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp>
+#include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
+#include <com/sun/star/ui/dialogs/ControlActions.hpp>
+#include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
+
+#include <osl/mutex.hxx>
+
+#include <vcl/fpicker.hrc>
+#include <vcl/svapp.hxx>
+#include <vcl/sysdata.hxx>
+#include <vcl/syswin.hxx>
+
+#include "osl/file.h"
+
+#include "FPServiceInfo.hxx"
+#include "VCLKDEApplication.hxx"
+/*
+#include <kfilefiltercombo.h>
+#include <kfilewidget.h>
+#include <kdiroperator.h>
+#include <kservicetypetrader.h>
+#include <kmessagebox.h>
+*/
+
+#include <kwindowsystem.h>
+
+// #include <QtCore/QDebug>
+#include <QtCore/QUrl>
+#include <QtGui/QClipboard>
+#include <QtWidgets/QCheckBox>
+#include <QtWidgets/QFileDialog>
+#include <QtWidgets/QGridLayout>
+#include <QtWidgets/QWidget>
+#include <QtCore/QThread>
+
+#undef Region
+
+#include "generic/geninst.h"
+
+#include "svids.hrc"
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::ui::dialogs;
+using namespace ::com::sun::star::ui::dialogs::TemplateDescription;
+using namespace ::com::sun::star::ui::dialogs::ExtendedFilePickerElementIds;
+using namespace ::com::sun::star::ui::dialogs::CommonFilePickerElementIds;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::uno;
+
+// The dialog should check whether LO also supports the protocol
+// provided by KIO, and KFileWidget::dirOperator() is only 4.3+ .
+// Moreover it's only in this somewhat internal KFileWidget class,
+// which may not necessarily be what QFileDialog::fileWidget() returns,
+// but that's hopefully not a problem in practice.
+//#if KDE_VERSION_MAJOR == 4 && KDE_VERSION_MINOR >= 2
+//#define ALLOW_REMOTE_URLS 1
+//#else
+#define ALLOW_REMOTE_URLS 0
+//#endif
+
+// helper functions
+
+
+namespace
+{
+    uno::Sequence<OUString> SAL_CALL FilePicker_getSupportedServiceNames()
+    {
+        uno::Sequence<OUString> aRet(3);
+        aRet[0] = "com.sun.star.ui.dialogs.FilePicker";
+        aRet[1] = "com.sun.star.ui.dialogs.SystemFilePicker";
+        aRet[2] = "com.sun.star.ui.dialogs.KDE5FilePicker";
+        return aRet;
+    }
+}
+
+OUString toOUString(const QString& s)
+{
+    // QString stores UTF16, just like OUString
+    return OUString(reinterpret_cast<const sal_Unicode*>(s.data()), s.length());
+}
+
+QString toQString(const OUString& s)
+{
+    return QString::fromUtf16(
+        reinterpret_cast<ushort const *>(s.getStr()), s.getLength());
+}
+
+// KDE5FilePicker
+
+KDE5FilePicker::KDE5FilePicker( const uno::Reference<uno::XComponentContext>& )
+    : KDE5FilePicker_Base(_helperMutex)
+    , allowRemoteUrls( false )
+{
+    _extraControls = new QWidget();
+    _layout = new QGridLayout(_extraControls);
+
+    _dialog = new QFileDialog(nullptr, QString(""), QString("~"));
+//   _extraControls);
+#if ALLOW_REMOTE_URLS
+    if( KFileWidget* fileWidget = dynamic_cast< KFileWidget* >( _dialog->fileWidget()))
+    {
+        allowRemoteUrls = true;
+        // Use finishedLoading signal rather than e.g. urlEntered, because if there's a problem
+        // such as the URL being mistyped, there's no way to prevent two message boxes about it,
+        // one from us and one from KDE code.
+        connect( fileWidget->dirOperator(), SIGNAL( finishedLoading()), SLOT( checkProtocol()));
+    }
+#endif
+
+    setMultiSelectionMode( false );
+
+    // XExecutableDialog functions
+    connect( this, SIGNAL( setTitleSignal( const OUString & ) ),
+             this, SLOT( setTitleSlot( const OUString & ) ), Qt::BlockingQueuedConnection );
+    connect( this, SIGNAL( executeSignal() ),
+             this, SLOT( executeSlot() ), Qt::BlockingQueuedConnection );
+
+    // XFilePicker functions
+    connect( this, SIGNAL( setMultiSelectionModeSignal( bool ) ),
+             this, SLOT( setMultiSelectionModeSlot( bool ) ), Qt::BlockingQueuedConnection );
+    connect( this, SIGNAL( setDefaultNameSignal( const OUString & ) ),
+             this, SLOT( setDefaultNameSlot( const OUString & ) ), Qt::BlockingQueuedConnection );
+    connect( this, SIGNAL( setDisplayDirectorySignal( const OUString & ) ),
+             this, SLOT( setDisplayDirectorySlot( const OUString & ) ), Qt::BlockingQueuedConnection );
+    connect( this, SIGNAL( getDisplayDirectorySignal() ),
+             this, SLOT( getDisplayDirectorySlot() ), Qt::BlockingQueuedConnection );
+    connect( this, SIGNAL( getFilesSignal() ),
+             this, SLOT( getFilesSlot() ), Qt::BlockingQueuedConnection );
+
+    // XFilterManager functions
+    connect( this, SIGNAL( appendFilterSignal( const OUString &, const OUString & ) ),
+             this, SLOT( appendFilterSlot( const OUString &, const OUString & ) ), Qt::BlockingQueuedConnection );
+    connect( this, SIGNAL( setCurrentFilterSignal( const OUString & ) ),
+             this, SLOT( setCurrentFilterSlot( const OUString & ) ), Qt::BlockingQueuedConnection );
+    connect( this, SIGNAL( getCurrentFilterSignal() ),
+             this, SLOT( getCurrentFilterSlot() ), Qt::BlockingQueuedConnection );
+
+    // XFilterGroupManager functions
+    connect( this, SIGNAL( appendFilterGroupSignal( const OUString &, const css::uno::Sequence< css::beans::StringPair > & ) ),
+             this, SLOT( appendFilterGroupSlot( const OUString &, const css::uno::Sequence< css::beans::StringPair > & ) ), Qt::BlockingQueuedConnection );
+
+    // XFilePickerControlAccess functions
+    connect( this, SIGNAL( setValueSignal( sal_Int16, sal_Int16, const css::uno::Any & ) ),
+             this, SLOT( setValueSlot( sal_Int16, sal_Int16, const css::uno::Any & ) ), Qt::BlockingQueuedConnection );
+    connect( this, SIGNAL( getValueSignal( sal_Int16, sal_Int16 ) ),
+             this, SLOT( getValueSlot( sal_Int16, sal_Int16 ) ), Qt::BlockingQueuedConnection );
+    connect( this, SIGNAL( enableControlSignal( sal_Int16, bool ) ),
+             this, SLOT( enableControlSlot( sal_Int16, bool ) ), Qt::BlockingQueuedConnection );
+    connect( this, SIGNAL( setLabelSignal( sal_Int16, const OUString & ) ),
+             this, SLOT( setLabelSlot( sal_Int16, const OUString & ) ), Qt::BlockingQueuedConnection );
+    connect( this, SIGNAL( getLabelSignal( sal_Int16 ) ),
+             this, SLOT( getLabelSlot( sal_Int16 ) ), Qt::BlockingQueuedConnection );
+
+    // XFilePicker2 functions
+    connect( this, SIGNAL( getSelectedFilesSignal() ),
+             this, SLOT( getSelectedFilesSlot() ), Qt::BlockingQueuedConnection );
+
+    // XInitialization
+    connect( this, SIGNAL( initializeSignal( const css::uno::Sequence< css::uno::Any > & ) ),
+             this, SLOT( initializeSlot( const css::uno::Sequence< css::uno::Any > & ) ), Qt::BlockingQueuedConnection );
+
+    // Destructor proxy
+    connect( this, SIGNAL( cleanupProxySignal() ), this, SLOT( cleanupProxy() ), Qt::BlockingQueuedConnection );
+
+    connect( this, SIGNAL( checkProtocolSignal() ), this, SLOT( checkProtocol() ), Qt::BlockingQueuedConnection );
+
+    // XFilePickerListener notifications
+    connect( _dialog, SIGNAL( filterChanged(const QString&) ), this, SLOT( filterChanged(const QString&) ));
+    connect( _dialog, SIGNAL( selectionChanged() ), this, SLOT( selectionChanged() ));
+}
+
+KDE5FilePicker::~KDE5FilePicker()
+{
+    cleanupProxy();
+}
+
+void KDE5FilePicker::cleanupProxy()
+{
+    if( qApp->thread() != QThread::currentThread() ) {
+        SalYieldMutexReleaser aReleaser;
+        return Q_EMIT cleanupProxySignal();
+    }
+    delete _dialog;
+}
+
+void SAL_CALL KDE5FilePicker::addFilePickerListener( const uno::Reference<XFilePickerListener>& xListener )
+    throw( uno::RuntimeException, std::exception )
+{
+    SolarMutexGuard aGuard;
+    m_xListener = xListener;
+}
+
+void SAL_CALL KDE5FilePicker::removeFilePickerListener( const uno::Reference<XFilePickerListener>& )
+    throw( uno::RuntimeException, std::exception )
+{
+    SolarMutexGuard aGuard;
+    m_xListener.clear();
+}
+
+void SAL_CALL KDE5FilePicker::setTitle( const OUString &title )
+    throw( uno::RuntimeException, std::exception )
+{
+    if( qApp->thread() != QThread::currentThread() ) {
+        SalYieldMutexReleaser aReleaser;
+        return Q_EMIT setTitleSignal( title );
+    }
+
+    _dialog->setWindowTitle(toQString(title));
+}
+
+sal_Int16 SAL_CALL KDE5FilePicker::execute()
+    throw( uno::RuntimeException, std::exception )
+{
+    if( qApp->thread() != QThread::currentThread() ) {
+        SalYieldMutexReleaser aReleaser;
+        return Q_EMIT executeSignal();
+    }
+
+    //get the window id of the main OO window to set it for the dialog as a parent
+    vcl::Window *pParentWin = Application::GetDefDialogParent();
+    if ( pParentWin )
+    {
+        const SystemEnvData* pSysData = static_cast<SystemWindow *>(pParentWin)->GetSystemData();
+        if ( pSysData )
+        {
+            KWindowSystem::setMainWindow( _dialog, pSysData->aWindow); // unx only
+        }
+    }
+/*
+    _dialog->clearFilter();
+    _dialog->setFilter(_filter);
+
+    if(!_currentFilter.isNull())
+        _dialog->filterWidget()->setCurrentItem(_currentFilter);
+    _dialog->filterWidget()->setEditable(false);
+*/
+
+    VCLKDEApplication::preDialogSetup();
+    //block and wait for user input
+    int result = _dialog->exec();
+    VCLKDEApplication::postDialogCleanup();
+    if( result == QFileDialog::Accepted )
+        return ExecutableDialogResults::OK;
+
+    return ExecutableDialogResults::CANCEL;
+}
+
+void SAL_CALL KDE5FilePicker::setMultiSelectionMode( sal_Bool multiSelect )
+    throw( uno::RuntimeException, std::exception )
+{
+    if( qApp->thread() != QThread::currentThread() ) {
+        SalYieldMutexReleaser release;
+        return Q_EMIT setMultiSelectionModeSignal( multiSelect );
+    }
+
+    if (multiSelect)
+        _dialog->setFileMode(QFileDialog::ExistingFiles);
+    else
+        _dialog->setFileMode(QFileDialog::ExistingFile);
+}
+
+void SAL_CALL KDE5FilePicker::setDefaultName( const OUString &name )
+    throw( uno::RuntimeException, std::exception )
+{
+    if( qApp->thread() != QThread::currentThread() ) {
+        SalYieldMutexReleaser release;
+        return Q_EMIT setDefaultNameSignal( name );
+    }
+
+    _dialog->selectUrl(QUrl(toQString(name)));
+}
+
+void SAL_CALL KDE5FilePicker::setDisplayDirectory( const OUString &dir )
+    throw( uno::RuntimeException, std::exception )
+{
+    if( qApp->thread() != QThread::currentThread() ) {
+        SalYieldMutexReleaser release;
+        return Q_EMIT setDisplayDirectorySignal( dir );
+    }
+
+    _dialog->selectUrl(QUrl(toQString(dir)));
+}
+
+OUString SAL_CALL KDE5FilePicker::getDisplayDirectory()
+    throw( uno::RuntimeException, std::exception )
+{
+    if( qApp->thread() != QThread::currentThread() ) {
+        SalYieldMutexReleaser release;
+        return Q_EMIT getDisplayDirectorySignal();
+    }
+
+    return toOUString(_dialog->directoryUrl().url());
+}
+
+uno::Sequence< OUString > SAL_CALL KDE5FilePicker::getFiles()
+    throw( uno::RuntimeException, std::exception )
+{
+    if( qApp->thread() != QThread::currentThread() ) {
+        SalYieldMutexReleaser release;
+        return Q_EMIT getFilesSignal();
+    }
+    uno::Sequence< OUString > seq = getSelectedFiles();
+    if (seq.getLength() > 1)
+        seq.realloc(1);
+    return seq;
+}
+
+uno::Sequence< OUString > SAL_CALL KDE5FilePicker::getSelectedFiles()
+    throw( uno::RuntimeException, std::exception )
+{
+    if( qApp->thread() != QThread::currentThread() ) {
+        SalYieldMutexReleaser release;
+        return Q_EMIT getSelectedFilesSignal();
+    }
+    const QList<QUrl> urls = _dialog->selectedUrls();
+    uno::Sequence< OUString > seq( urls.size() );
+    int i = 0;
+    foreach( const QUrl& url, urls )
+        seq[ i++ ]= toOUString( url.url());
+    return seq;
+}
+
+void SAL_CALL KDE5FilePicker::appendFilter( const OUString &title, const OUString &filter )
+    throw( lang::IllegalArgumentException, uno::RuntimeException, std::exception )
+{
+    if( qApp->thread() != QThread::currentThread() ) {
+        SalYieldMutexReleaser release;
+        return Q_EMIT appendFilterSignal( title, filter );
+    }
+
+    QString t = toQString(title);
+    QString f = toQString(filter);
+
+    // '/' need to be escaped else they are assumed to be mime types by kfiledialog
+    //see the docs
+    t.replace("/", "\\/");
+
+    // openoffice gives us filters separated by ';' qt dialogs just want space separated
+    f.replace(";", " ");
+
+    // make sure "*.*" is not used as "all files"
+    f.replace("*.*", "*");
+
+    _filters << QString("%1 (%2)").arg(f).arg(t);
+}
+
+void SAL_CALL KDE5FilePicker::setCurrentFilter( const OUString &title )
+    throw( lang::IllegalArgumentException, uno::RuntimeException, std::exception )
+{
+    if( qApp->thread() != QThread::currentThread() ) {
+        SalYieldMutexReleaser release;
+        return Q_EMIT setCurrentFilterSignal( title );
+    }
+
+    _currentFilter = toQString(title);
+}
+
+OUString SAL_CALL KDE5FilePicker::getCurrentFilter()
+    throw( uno::RuntimeException, std::exception )
+{
+    if( qApp->thread() != QThread::currentThread() ) {
+        SalYieldMutexReleaser release;
+        return Q_EMIT getCurrentFilterSignal();
+    }
+
+    // _dialog->currentFilter() wouldn't quite work, because it returns only e.g. "*.doc",
+    // without the description, and there may be several filters with the same pattern
+    QString filter = _dialog->selectedNameFilter();
+    filter = filter.mid( filter.indexOf( '|' ) + 1 ); // convert from the pattern|description format if needed
+    filter.replace( "\\/", "/" );
+
+    //default if not found
+    if (filter.isNull())
+        filter = "ODF Text Document (.odt)";
+
+    return toOUString(filter);
+}
+
+void SAL_CALL KDE5FilePicker::appendFilterGroup( const OUString& rGroupTitle, const uno::Sequence<beans::StringPair>& filters)
+    throw( lang::IllegalArgumentException, uno::RuntimeException, std::exception )
+{
+    if( qApp->thread() != QThread::currentThread() ) {
+        SalYieldMutexReleaser release;
+        return Q_EMIT appendFilterGroupSignal( rGroupTitle, filters );
+    }
+
+    const sal_uInt16 length = filters.getLength();
+    for (sal_uInt16 i = 0; i < length; ++i)
+    {
+        beans::StringPair aPair = filters[i];
+        appendFilter( aPair.First, aPair.Second );
+    }
+}
+
+void SAL_CALL KDE5FilePicker::setValue( sal_Int16 controlId, sal_Int16 nControlAction, const uno::Any &value )
+    throw( uno::RuntimeException, std::exception )
+{
+    if( qApp->thread() != QThread::currentThread() ) {
+        SalYieldMutexReleaser release;
+        return Q_EMIT setValueSignal( controlId, nControlAction, value );
+    }
+
+    if (_customWidgets.contains( controlId )) {
+        QCheckBox* cb = dynamic_cast<QCheckBox*>( _customWidgets.value( controlId ));
+        if (cb)
+            cb->setChecked(value.get<bool>());
+    }
+    else
+        OSL_TRACE( "set label on unknown control %d", controlId );
+}
+
+uno::Any SAL_CALL KDE5FilePicker::getValue( sal_Int16 controlId, sal_Int16 nControlAction )
+    throw( uno::RuntimeException, std::exception )
+{
+    if (CHECKBOX_AUTOEXTENSION == controlId)
+        // We ignore this one and rely on QFileDialog to provide the function.
+        // Always return false, to pretend we do not support this, otherwise
+        // LO core would try to be smart and cut the extension in some places,
+        // interfering with QFileDialog's handling of it. QFileDialog also
+        // saves the value of the setting, so LO core is not needed for that either.
+        return uno::Any( false );
+
+    if( qApp->thread() != QThread::currentThread() ) {
+        SalYieldMutexReleaser release;
+        return Q_EMIT getValueSignal( controlId, nControlAction );
+    }
+
+    uno::Any res(false);
+    if (_customWidgets.contains( controlId )) {
+        QCheckBox* cb = dynamic_cast<QCheckBox*>( _customWidgets.value( controlId ));
+        if (cb)
+            res = uno::Any(cb->isChecked());
+    }
+    else
+        OSL_TRACE( "get value on unknown control %d", controlId );
+
+    return res;
+}
+
+void SAL_CALL KDE5FilePicker::enableControl( sal_Int16 controlId, sal_Bool enable )
+    throw( uno::RuntimeException, std::exception )
+{
+    if( qApp->thread() != QThread::currentThread() ) {
+        SalYieldMutexReleaser release;
+        return Q_EMIT enableControlSignal( controlId, enable );
+    }
+
+    if (_customWidgets.contains( controlId ))
+        _customWidgets.value( controlId )->setEnabled( enable );
+    else
+        OSL_TRACE("enable unknown control %d", controlId );
+}
+
+void SAL_CALL KDE5FilePicker::setLabel( sal_Int16 controlId, const OUString &label )
+    throw( uno::RuntimeException, std::exception )
+{
+    if( qApp->thread() != QThread::currentThread() ) {
+        SalYieldMutexReleaser release;
+        return Q_EMIT setLabelSignal( controlId, label );
+    }
+
+    if (_customWidgets.contains( controlId )) {
+        QCheckBox* cb = dynamic_cast<QCheckBox*>( _customWidgets.value( controlId ));
+        if (cb)
+            cb->setText( toQString(label) );
+    }
+    else
+        OSL_TRACE( "set label on unknown control %d", controlId );
+}
+
+OUString SAL_CALL KDE5FilePicker::getLabel(sal_Int16 controlId)
+    throw ( uno::RuntimeException, std::exception )
+{
+    if( qApp->thread() != QThread::currentThread() ) {
+        SalYieldMutexReleaser release;
+        return Q_EMIT getLabelSignal( controlId );
+    }
+
+    QString label;
+    if (_customWidgets.contains( controlId )) {
+        QCheckBox* cb = dynamic_cast<QCheckBox*>( _customWidgets.value( controlId ));
+        if (cb)
+            label = cb->text();
+    }
+    else
+        OSL_TRACE( "get label on unknown control %d", controlId );
+
+    return toOUString(label);
+}
+
+QString KDE5FilePicker::getResString( sal_Int16 aRedId )
+{
+    QString aResString;
+
+    if( aRedId < 0 )
+        return aResString;
+
+    try
+    {
+        aResString = toQString(ResId(aRedId, *ImplGetResMgr()).toString());
+    }
+    catch(...)
+    {
+    }
+
+    return aResString.replace('~', '&');
+}
+
+void KDE5FilePicker::addCustomControl(sal_Int16 controlId)
+{
+    QWidget* widget = nullptr;
+    sal_Int32 resId = -1;
+
+    switch (controlId)
+    {
+        case CHECKBOX_AUTOEXTENSION:
+            resId = STR_FPICKER_AUTO_EXTENSION;
+            break;
+        case CHECKBOX_PASSWORD:
+            resId = STR_FPICKER_PASSWORD;
+            break;
+        case CHECKBOX_FILTEROPTIONS:
+            resId = STR_FPICKER_FILTER_OPTIONS;
+            break;
+        case CHECKBOX_READONLY:
+            resId = STR_FPICKER_READONLY;
+            break;
+        case CHECKBOX_LINK:
+            resId = STR_FPICKER_INSERT_AS_LINK;
+            break;
+        case CHECKBOX_PREVIEW:
+            resId = STR_FPICKER_SHOW_PREVIEW;
+            break;
+        case CHECKBOX_SELECTION:
+            resId = STR_FPICKER_SELECTION;
+            break;
+        case PUSHBUTTON_PLAY:
+            resId = STR_FPICKER_PLAY;
+            break;
+        case LISTBOX_VERSION:
+            resId = STR_FPICKER_VERSION;
+            break;
+        case LISTBOX_TEMPLATE:
+            resId = STR_FPICKER_TEMPLATES;
+            break;
+        case LISTBOX_IMAGE_TEMPLATE:
+            resId = STR_FPICKER_IMAGE_TEMPLATE;
+            break;
+        case LISTBOX_VERSION_LABEL:
+        case LISTBOX_TEMPLATE_LABEL:
+        case LISTBOX_IMAGE_TEMPLATE_LABEL:
+        case LISTBOX_FILTER_SELECTOR:
+            break;
+    }
+
+    switch (controlId)
+    {
+        case CHECKBOX_AUTOEXTENSION:
+        case CHECKBOX_PASSWORD:
+        case CHECKBOX_FILTEROPTIONS:
+        case CHECKBOX_READONLY:
+        case CHECKBOX_LINK:
+        case CHECKBOX_PREVIEW:
+        case CHECKBOX_SELECTION:
+        {
+            widget = new QCheckBox(getResString(resId), _extraControls);
+
+            // the checkbox is created even for CHECKBOX_AUTOEXTENSION to simplify
+            // code, but the checkbox is hidden and ignored
+            if( controlId == CHECKBOX_AUTOEXTENSION )
+                widget->hide();
+
+            break;
+        }
+        case PUSHBUTTON_PLAY:
+        case LISTBOX_VERSION:
+        case LISTBOX_TEMPLATE:
+        case LISTBOX_IMAGE_TEMPLATE:
+        case LISTBOX_VERSION_LABEL:
+        case LISTBOX_TEMPLATE_LABEL:
+        case LISTBOX_IMAGE_TEMPLATE_LABEL:
+        case LISTBOX_FILTER_SELECTOR:
+            break;
+    }
+
+    if (widget)
+    {
+        _layout->addWidget(widget);
+        _customWidgets.insert(controlId, widget);
+    }
+}
+
+void SAL_CALL KDE5FilePicker::initialize( const uno::Sequence<uno::Any> &args )
+    throw( uno::Exception, uno::RuntimeException, std::exception )
+{
+    if( qApp->thread() != QThread::currentThread() ) {
+        SalYieldMutexReleaser release;
+        return Q_EMIT initializeSignal( args );
+    }
+
+    _filters.clear();
+    _currentFilter.clear();
+
+    // parameter checking
+    uno::Any arg;
+    if (args.getLength() == 0)
+    {
+        throw lang::IllegalArgumentException(
+                OUString( "no arguments" ),
+                static_cast< XFilePicker2* >( this ), 1 );
+    }
+
+    arg = args[0];
+
+    if (( arg.getValueType() != cppu::UnoType<sal_Int16>::get()) &&
+        ( arg.getValueType() != cppu::UnoType<sal_Int8>::get()))
+    {
+        throw lang::IllegalArgumentException(
+                OUString( "invalid argument type" ),
+                static_cast< XFilePicker2* >( this ), 1 );
+    }
+
+    sal_Int16 templateId = -1;
+    arg >>= templateId;
+
+    //default is opening
+    QFileDialog::AcceptMode operationMode = QFileDialog::AcceptOpen;
+
+    switch ( templateId )
+    {
+        case FILEOPEN_SIMPLE:
+            break;
+
+        case FILESAVE_SIMPLE:
+            operationMode = QFileDialog::AcceptSave;
+            break;
+
+        case FILESAVE_AUTOEXTENSION:
+            operationMode = QFileDialog::AcceptSave;
+            addCustomControl( CHECKBOX_AUTOEXTENSION );
+            break;
+
+        case FILESAVE_AUTOEXTENSION_PASSWORD:
+        {
+            operationMode = QFileDialog::AcceptSave;
+            addCustomControl( CHECKBOX_PASSWORD );
+            break;
+        }
+        case FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS:
+        {
+            operationMode = QFileDialog::AcceptSave;
+            addCustomControl( CHECKBOX_AUTOEXTENSION );
+            addCustomControl( CHECKBOX_PASSWORD );
+            addCustomControl( CHECKBOX_FILTEROPTIONS );
+            break;
+        }
+        case FILESAVE_AUTOEXTENSION_SELECTION:
+            operationMode = QFileDialog::AcceptSave;
+            addCustomControl( CHECKBOX_AUTOEXTENSION );
+            addCustomControl( CHECKBOX_SELECTION );
+            break;
+
+        case FILESAVE_AUTOEXTENSION_TEMPLATE:
+            operationMode = QFileDialog::AcceptSave;
+            addCustomControl( CHECKBOX_AUTOEXTENSION );
+            addCustomControl( LISTBOX_TEMPLATE );
+            break;
+
+        case FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE:
+            addCustomControl( CHECKBOX_LINK );
+            addCustomControl( CHECKBOX_PREVIEW );
+            addCustomControl( LISTBOX_IMAGE_TEMPLATE );
+            break;
+
+        case FILEOPEN_PLAY:
+            addCustomControl( PUSHBUTTON_PLAY );
+            break;
+
+        case FILEOPEN_READONLY_VERSION:
+            addCustomControl( CHECKBOX_READONLY );
+            addCustomControl( LISTBOX_VERSION );
+            break;
+
+        case FILEOPEN_LINK_PREVIEW:
+            addCustomControl( CHECKBOX_LINK );
+            addCustomControl( CHECKBOX_PREVIEW );
+            break;
+
+        default:
+            throw lang::IllegalArgumentException(
+                    OUString( "Unknown template" ),
+                    static_cast< XFilePicker2* >( this ),
+                    1 );
+    }
+
+    _dialog->setAcceptMode( operationMode );
+
+    sal_Int16 resId = -1;
+    switch (_dialog->acceptMode())
+    {
+    case QFileDialog::AcceptOpen:
+        resId = STR_FPICKER_OPEN;
+        break;
+    case QFileDialog::AcceptSave:
+        resId = STR_FPICKER_SAVE;
+        _dialog->setConfirmOverwrite( true );
+        break;
+    default:
+        break;
+    }
+
+    _dialog->setWindowTitle(getResString(resId));
+}
+
+void SAL_CALL KDE5FilePicker::cancel()
+    throw ( uno::RuntimeException, std::exception )
+{
+
+}
+
+void SAL_CALL KDE5FilePicker::disposing( const lang::EventObject &rEvent )
+    throw( uno::RuntimeException )
+{
+    uno::Reference<XFilePickerListener> xFilePickerListener( rEvent.Source, uno::UNO_QUERY );
+
+    if ( xFilePickerListener.is() )
+    {
+        removeFilePickerListener( xFilePickerListener );
+    }
+}
+
+OUString SAL_CALL KDE5FilePicker::getImplementationName()
+    throw( uno::RuntimeException, std::exception )
+{
+    return OUString( FILE_PICKER_IMPL_NAME );
+}
+
+sal_Bool SAL_CALL KDE5FilePicker::supportsService( const OUString& ServiceName )
+    throw( uno::RuntimeException, std::exception )
+{
+    return cppu::supportsService(this, ServiceName);
+}
+
+uno::Sequence< OUString > SAL_CALL KDE5FilePicker::getSupportedServiceNames()
+    throw( uno::RuntimeException, std::exception )
+{
+    return FilePicker_getSupportedServiceNames();
+}
+
+void KDE5FilePicker::checkProtocol()
+{
+    if( qApp->thread() != QThread::currentThread() ) {
+        SalYieldMutexReleaser release;
+        return Q_EMIT checkProtocolSignal();
+    }
+
+    // There's no libreoffice.desktop :(, so find a matching one.
+/*
+    KService::List services = KServiceTypeTrader::self()->query( "Application", "Exec =~ 'libreoffice %U'" );
+    QStringList protocols;
+    if( !services.isEmpty())
+        protocols = services[ 0 ]->property( "X-KDE-Protocols" ).toStringList();
+    if( protocols.isEmpty()) // incorrect (developer?) installation ?
+        protocols << "file" << "http";
+    if( !protocols.contains( _dialog->baseUrl().protocol()) && !protocols.contains( "KIO" ))
+        KMessageBox::error( _dialog, KIO::buildErrorString( KIO::ERR_UNSUPPORTED_PROTOCOL, _dialog->baseUrl().protocol()));
+*/
+}
+
+void KDE5FilePicker::filterChanged(const QString &)
+{
+    FilePickerEvent aEvent;
+    aEvent.ElementId = LISTBOX_FILTER;
+    OSL_TRACE( "filter changed" );
+    if (m_xListener.is())
+        m_xListener->controlStateChanged( aEvent );
+}
+
+void KDE5FilePicker::selectionChanged()
+{
+    FilePickerEvent aEvent;
+    OSL_TRACE( "file selection changed" );
+    if (m_xListener.is())
+        m_xListener->fileSelectionChanged( aEvent );
+}
+
+#include "KDE5FilePicker.moc"
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/kde5/KDE5FilePicker.hxx b/vcl/unx/kde5/KDE5FilePicker.hxx
new file mode 100644
index 0000000..ab71a1e
--- /dev/null
+++ b/vcl/unx/kde5/KDE5FilePicker.hxx
@@ -0,0 +1,237 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <cppuhelper/compbase.hxx>
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/ui/dialogs/XFilePicker3.hpp>
+#include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+#include <osl/conditn.hxx>
+#include <osl/mutex.hxx>
+
+#include <rtl/ustrbuf.hxx>
+
+#include <QtCore/QObject>
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+#include <QtCore/QHash>
+
+class QFileDialog;
+class QWidget;
+class QLayout;
+
+typedef ::cppu::WeakComponentImplHelper
+<   css::ui::dialogs::XFilePicker3
+,   css::ui::dialogs::XFilePickerControlAccess
+// TODO css::ui::dialogs::XFilePreview
+,   css::lang::XInitialization
+,   css::lang::XServiceInfo
+> KDE5FilePicker_Base;
+
+class KDE5FilePicker
+    : public QObject
+    , public KDE5FilePicker_Base
+{
+    Q_OBJECT
+protected:
+
+    css::uno::Reference< css::ui::dialogs::XFilePickerListener > m_xListener;
+
+    //the dialog to display
+    QFileDialog* _dialog;
+
+    osl::Mutex _helperMutex;
+
+    //running filter string to add to dialog
+    QStringList _filters;
+    // string to set the current filter
+    QString _currentFilter;
+
+    //mapping of SAL control ID's to created custom controls
+    QHash<sal_Int16, QWidget*> _customWidgets;
+
+    //widget to contain extra custom controls
+    QWidget* _extraControls;
+
+    //layout for extra custom controls
+    QLayout* _layout;
+
+    bool allowRemoteUrls;
+
+public:
+    explicit KDE5FilePicker( const css::uno::Reference< css::uno::XComponentContext >& );
+    virtual ~KDE5FilePicker();
+
+    // XFilePickerNotifier
+    virtual void SAL_CALL addFilePickerListener( const css::uno::Reference< css::ui::dialogs::XFilePickerListener >& xListener ) throw( css::uno::RuntimeException, std::exception ) override;
+    virtual void SAL_CALL removeFilePickerListener( const css::uno::Reference< css::ui::dialogs::XFilePickerListener >& xListener ) throw( css::uno::RuntimeException, std::exception ) override;
+
+    // XExecutableDialog functions
+    virtual void SAL_CALL setTitle( const OUString &rTitle ) throw( css::uno::RuntimeException, std::exception ) override;
+    virtual sal_Int16 SAL_CALL execute() throw( css::uno::RuntimeException, std::exception ) override;
+
+    // XFilePicker functions
+    virtual void SAL_CALL setMultiSelectionMode( sal_Bool bMode ) throw( css::uno::RuntimeException, std::exception ) override;
+    virtual void SAL_CALL setDefaultName( const OUString &rName ) throw( css::uno::RuntimeException, std::exception ) override;
+    virtual void SAL_CALL setDisplayDirectory( const OUString &rDirectory ) throw( css::uno::RuntimeException, std::exception ) override;
+    virtual OUString SAL_CALL getDisplayDirectory() throw( css::uno::RuntimeException, std::exception ) override;
+    virtual css::uno::Sequence< OUString > SAL_CALL getFiles() throw( css::uno::RuntimeException, std::exception ) override;
+
+    // XFilterManager functions
+    virtual void SAL_CALL appendFilter( const OUString &rTitle, const OUString &rFilter ) throw( css::lang::IllegalArgumentException, css::uno::RuntimeException, std::exception ) override;
+    virtual void SAL_CALL setCurrentFilter( const OUString &rTitle ) throw( css::lang::IllegalArgumentException, css::uno::RuntimeException, std::exception ) override;
+    virtual OUString SAL_CALL getCurrentFilter() throw( css::uno::RuntimeException, std::exception ) override;
+
+    // XFilterGroupManager functions
+    virtual void SAL_CALL appendFilterGroup( const OUString &rGroupTitle, const css::uno::Sequence< css::beans::StringPair > &rFilters ) throw (css::lang::IllegalArgumentException, css::uno::RuntimeException, std::exception) override;
+
+    // XFilePickerControlAccess functions
+    virtual void SAL_CALL setValue( sal_Int16 nControlId, sal_Int16 nControlAction, const css::uno::Any &rValue ) throw (css::uno::RuntimeException, std::exception) override;
+    virtual css::uno::Any SAL_CALL getValue( sal_Int16 nControlId, sal_Int16 nControlAction ) throw (css::uno::RuntimeException, std::exception) override;
+    virtual void SAL_CALL enableControl( sal_Int16 nControlId, sal_Bool bEnable ) throw( css::uno::RuntimeException, std::exception ) override;
+    virtual void SAL_CALL setLabel( sal_Int16 nControlId, const OUString &rLabel ) throw (css::uno::RuntimeException, std::exception) override;
+    virtual OUString SAL_CALL getLabel( sal_Int16 nControlId ) throw (css::uno::RuntimeException, std::exception) override;
+
+    /* TODO XFilePreview
+
+    virtual css::uno::Sequence< sal_Int16 > SAL_CALL getSupportedImageFormats(  ) throw (css::uno::RuntimeException);
+    virtual sal_Int32 SAL_CALL  getTargetColorDepth(  ) throw (css::uno::RuntimeException);
+    virtual sal_Int32 SAL_CALL  getAvailableWidth(  ) throw (css::uno::RuntimeException);
+    virtual sal_Int32 SAL_CALL  getAvailableHeight(  ) throw (css::uno::RuntimeException);
+    virtual void SAL_CALL       setImage( sal_Int16 aImageFormat, const css::uno::Any &rImage ) throw (css::lang::IllegalArgumentException, css::uno::RuntimeException);
+    virtual sal_Bool SAL_CALL   setShowState( sal_Bool bShowState ) throw (css::uno::RuntimeException);
+    virtual sal_Bool SAL_CALL   getShowState(  ) throw (css::uno::RuntimeException);
+    */
+
+    // XFilePicker2 functions
+    virtual css::uno::Sequence< OUString > SAL_CALL getSelectedFiles()
+            throw (css::uno::RuntimeException, std::exception) override;
+
+    // XInitialization
+    virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any > &rArguments ) throw( css::uno::Exception, css::uno::RuntimeException, std::exception ) override;
+
+    // XCancellable
+    virtual void SAL_CALL cancel( ) throw( css::uno::RuntimeException, std::exception ) override;
+
+    // XEventListener
+    virtual void SAL_CALL disposing( const css::lang::EventObject &rEvent ) throw( css::uno::RuntimeException );
+    using cppu::WeakComponentImplHelperBase::disposing;
+
+    // XServiceInfo
+    virtual OUString SAL_CALL getImplementationName() throw( css::uno::RuntimeException, std::exception ) override;
+    virtual sal_Bool SAL_CALL supportsService( const OUString &rServiceName ) throw( css::uno::RuntimeException, std::exception ) override;
+    virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() throw( css::uno::RuntimeException, std::exception ) override;
+
+private Q_SLOTS:
+    // XExecutableDialog functions
+    void setTitleSlot( const OUString &rTitle ) throw( css::uno::RuntimeException ) { return setTitle( rTitle ); }
+    sal_Int16 executeSlot() throw( css::uno::RuntimeException ) { return execute(); }
+
+    // XFilePicker functions
+    void setMultiSelectionModeSlot( bool bMode ) throw( css::uno::RuntimeException ) { return setMultiSelectionMode( bMode ); }
+    void setDefaultNameSlot( const OUString &rName ) throw( css::uno::RuntimeException ) { return setDefaultName( rName ); }
+    void setDisplayDirectorySlot( const OUString &rDirectory ) throw( css::uno::RuntimeException ) { return setDisplayDirectory( rDirectory ); }
+    OUString getDisplayDirectorySlot() throw( css::uno::RuntimeException ) { return getDisplayDirectory(); }
+    css::uno::Sequence< OUString > getFilesSlot() throw( css::uno::RuntimeException ) { return getFiles(); }
+
+    // XFilterManager functions
+    void appendFilterSlot( const OUString &rTitle, const OUString &rFilter ) throw( css::lang::IllegalArgumentException, css::uno::RuntimeException ) { return appendFilter( rTitle, rFilter ); }
+    void setCurrentFilterSlot( const OUString &rTitle ) throw( css::lang::IllegalArgumentException, css::uno::RuntimeException ) { return setCurrentFilter( rTitle ); }
+    OUString getCurrentFilterSlot() throw( css::uno::RuntimeException ) { return getCurrentFilter(); }
+
+    // XFilterGroupManager functions
+    void appendFilterGroupSlot( const OUString &rGroupTitle, const css::uno::Sequence< css::beans::StringPair > &rFilters ) throw (css::lang::IllegalArgumentException, css::uno::RuntimeException) { return appendFilterGroup( rGroupTitle, rFilters ); }
+
+    // XFilePickerControlAccess functions
+    void setValueSlot( sal_Int16 nControlId, sal_Int16 nControlAction, const css::uno::Any &rValue ) throw (css::uno::RuntimeException) { return setValue( nControlId, nControlAction, rValue ); }
+    css::uno::Any getValueSlot( sal_Int16 nControlId, sal_Int16 nControlAction ) throw (css::uno::RuntimeException) { return getValue( nControlId, nControlAction ); }
+    void enableControlSlot( sal_Int16 nControlId, bool bEnable ) throw( css::uno::RuntimeException ) { return enableControl( nControlId, bEnable ); }
+    void setLabelSlot( sal_Int16 nControlId, const OUString &rLabel ) throw (css::uno::RuntimeException) { return setLabel( nControlId, rLabel ); }
+    OUString getLabelSlot( sal_Int16 nControlId ) throw (css::uno::RuntimeException) { return getLabel( nControlId ); }
+
+    // XFilePicker2 functions
+    css::uno::Sequence< OUString > getSelectedFilesSlot() throw (css::uno::RuntimeException) { return getSelectedFiles(); }
+
+    // XInitialization
+    void initializeSlot( const css::uno::Sequence< css::uno::Any > &rArguments ) throw( css::uno::Exception, css::uno::RuntimeException ) { return initialize( rArguments ); }
+
+Q_SIGNALS:
+    // XExecutableDialog functions
+    void setTitleSignal( const OUString &rTitle );
+    sal_Int16 executeSignal();
+
+    // XFilePicker functions
+    void setMultiSelectionModeSignal( bool bMode );
+    void setDefaultNameSignal( const OUString &rName );
+    void setDisplayDirectorySignal( const OUString &rDirectory );
+    OUString getDisplayDirectorySignal();
+    css::uno::Sequence< OUString > getFilesSignal();
+
+    // XFilterManager functions
+    void appendFilterSignal( const OUString &rTitle, const OUString &rFilter );
+    void setCurrentFilterSignal( const OUString &rTitle );
+    OUString getCurrentFilterSignal();
+
+    // XFilterGroupManager functions
+    void appendFilterGroupSignal( const OUString &rGroupTitle, const css::uno::Sequence< css::beans::StringPair > &rFilters );
+
+    // XFilePickerControlAccess functions
+    void setValueSignal( sal_Int16 nControlId, sal_Int16 nControlAction, const css::uno::Any &rValue );
+    css::uno::Any getValueSignal( sal_Int16 nControlId, sal_Int16 nControlAction );
+    void enableControlSignal( sal_Int16 nControlId, bool bEnable );
+    void setLabelSignal( sal_Int16 nControlId, const OUString &rLabel );
+    OUString getLabelSignal( sal_Int16 nControlId );
+
+    // XFilePicker2 functions
+    css::uno::Sequence< OUString > getSelectedFilesSignal() ;
+
+    // XInitialization
+    void initializeSignal( const css::uno::Sequence< css::uno::Any > &rArguments );
+
+    // Destructor proxy
+    void cleanupProxySignal();
+
+    // KDE protocol lookup
+    void checkProtocolSignal();
+
+private:
+    KDE5FilePicker( const KDE5FilePicker& ) = delete;
+    KDE5FilePicker& operator=( const KDE5FilePicker& ) = delete;
+
+    //add a custom control widget to the file dialog
+    void addCustomControl(sal_Int16 controlId);
+
+    static QString getResString( sal_Int16 aRedId );
+
+private Q_SLOTS:
+    void cleanupProxy();
+    void checkProtocol();
+
+    // emit XFilePickerListener controlStateChanged event
+    void filterChanged(const QString &filter);
+    // emit XFilePickerListener fileSelectionChanged event
+    void selectionChanged();
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/kde5/KDEData.cxx b/vcl/unx/kde5/KDEData.cxx
new file mode 100644
index 0000000..714b9a4
--- /dev/null
+++ b/vcl/unx/kde5/KDEData.cxx
@@ -0,0 +1,64 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <QtWidgets/QStyle>
+#include <QtWidgets/QApplication>
+
+#undef Region
+
+#include "KDEData.hxx"
+
+#include "KDEXLib.hxx"
+#include "KDESalDisplay.hxx"
+
+KDEData::~KDEData()
+{
+}
+
+void KDEData::Init()
+{
+    pXLib_ = new KDEXLib();
+    pXLib_->Init();
+    SetDisplay( SalKDEDisplay::self() );
+}
+
+void KDEData::initNWF()
+{
+    ImplSVData *pSVData = ImplGetSVData();
+
+    // draw toolbars on separate lines
+    pSVData->maNWFData.mbDockingAreaSeparateTB = true;
+    // no borders for menu, theming does that
+    pSVData->maNWFData.mbFlatMenu = true;
+
+    // Styled menus need additional space
+    QStyle *style = QApplication::style();
+    pSVData->maNWFData.mnMenuFormatBorderX =
+       style->pixelMetric( QStyle::PM_MenuPanelWidth ) +
+       style->pixelMetric( QStyle::PM_MenuHMargin );
+    pSVData->maNWFData.mnMenuFormatBorderY =
+       style->pixelMetric( QStyle::PM_MenuPanelWidth ) +
+       style->pixelMetric( QStyle::PM_MenuVMargin );
+}
+
+void KDEData::deInitNWF()
+{
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/kde5/KDEData.hxx b/vcl/unx/kde5/KDEData.hxx
new file mode 100644
index 0000000..112aaf5
--- /dev/null
+++ b/vcl/unx/kde5/KDEData.hxx
@@ -0,0 +1,37 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <unx/saldisp.hxx>
+#include <unx/saldata.hxx>
+
+class KDEData : public X11SalData
+{
+    public:
+        explicit KDEData( SalInstance *pInstance )
+                        : X11SalData( SAL_DATA_KDE5, pInstance ) {}
+        virtual ~KDEData();
+
+        virtual void Init() override;
+        virtual void initNWF() override;
+        virtual void deInitNWF() override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/kde5/KDESalDisplay.cxx b/vcl/unx/kde5/KDESalDisplay.cxx
new file mode 100644
index 0000000..8ec2615
--- /dev/null
+++ b/vcl/unx/kde5/KDESalDisplay.cxx
@@ -0,0 +1,112 @@

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list