summaryrefslogtreecommitdiffstats
path: root/kioslave/media
diff options
context:
space:
mode:
Diffstat (limited to 'kioslave/media')
-rw-r--r--kioslave/media/Makefile.am36
-rw-r--r--kioslave/media/configure.in.in184
-rw-r--r--kioslave/media/contrib/README18
-rwxr-xr-xkioslave/media/contrib/mediamanager_usbstorage.dev108
-rwxr-xr-xkioslave/media/contrib/usbcam82
-rw-r--r--kioslave/media/dummy.cpp1
-rw-r--r--kioslave/media/kcmodule/Makefile.am21
-rw-r--r--kioslave/media/kcmodule/main.cpp103
-rw-r--r--kioslave/media/kcmodule/main.h45
-rw-r--r--kioslave/media/kcmodule/managermodule.cpp74
-rw-r--r--kioslave/media/kcmodule/managermodule.h34
-rw-r--r--kioslave/media/kcmodule/managermoduleview.ui72
-rw-r--r--kioslave/media/kcmodule/media.desktop197
-rw-r--r--kioslave/media/kcmodule/mimetypelistboxitem.cpp35
-rw-r--r--kioslave/media/kcmodule/mimetypelistboxitem.h37
-rw-r--r--kioslave/media/kcmodule/notifiermodule.cpp230
-rw-r--r--kioslave/media/kcmodule/notifiermodule.h57
-rw-r--r--kioslave/media/kcmodule/notifiermoduleview.ui171
-rw-r--r--kioslave/media/kcmodule/serviceconfigdialog.cpp151
-rw-r--r--kioslave/media/kcmodule/serviceconfigdialog.h48
-rw-r--r--kioslave/media/kcmodule/serviceview.ui248
-rw-r--r--kioslave/media/kfile-plugin/Makefile.am13
-rw-r--r--kioslave/media/kfile-plugin/kfile_media.desktop75
-rw-r--r--kioslave/media/kfile-plugin/kfilemediaplugin.cpp197
-rw-r--r--kioslave/media/kfile-plugin/kfilemediaplugin.h47
-rw-r--r--kioslave/media/kio_media.cpp275
-rw-r--r--kioslave/media/kio_media.h54
-rw-r--r--kioslave/media/libmediacommon/Makefile.am11
-rw-r--r--kioslave/media/libmediacommon/actionlistboxitem.cpp47
-rw-r--r--kioslave/media/libmediacommon/actionlistboxitem.h40
-rw-r--r--kioslave/media/libmediacommon/mediamanagersettings.kcfg23
-rw-r--r--kioslave/media/libmediacommon/mediamanagersettings.kcfgc4
-rw-r--r--kioslave/media/libmediacommon/medium.cpp228
-rw-r--r--kioslave/media/libmediacommon/medium.h110
-rw-r--r--kioslave/media/libmediacommon/notifieraction.cpp97
-rw-r--r--kioslave/media/libmediacommon/notifieraction.h60
-rw-r--r--kioslave/media/libmediacommon/notifiernothingaction.cpp39
-rw-r--r--kioslave/media/libmediacommon/notifiernothingaction.h34
-rw-r--r--kioslave/media/libmediacommon/notifieropenaction.cpp45
-rw-r--r--kioslave/media/libmediacommon/notifieropenaction.h34
-rw-r--r--kioslave/media/libmediacommon/notifierserviceaction.cpp166
-rw-r--r--kioslave/media/libmediacommon/notifierserviceaction.h61
-rw-r--r--kioslave/media/libmediacommon/notifiersettings.cpp379
-rw-r--r--kioslave/media/libmediacommon/notifiersettings.h63
-rw-r--r--kioslave/media/media.protocol18
-rw-r--r--kioslave/media/mediaimpl.cpp429
-rw-r--r--kioslave/media/mediaimpl.h81
-rw-r--r--kioslave/media/mediamanager/Makefile.am32
-rw-r--r--kioslave/media/mediamanager/backendbase.cpp26
-rw-r--r--kioslave/media/mediamanager/backendbase.h35
-rw-r--r--kioslave/media/mediamanager/fstabbackend.cpp483
-rw-r--r--kioslave/media/mediamanager/fstabbackend.h68
-rw-r--r--kioslave/media/mediamanager/halbackend.cpp1345
-rw-r--r--kioslave/media/mediamanager/halbackend.h228
-rw-r--r--kioslave/media/mediamanager/linuxcdpolling.cpp585
-rw-r--r--kioslave/media/mediamanager/linuxcdpolling.h86
-rw-r--r--kioslave/media/mediamanager/mediadirnotify.cpp124
-rw-r--r--kioslave/media/mediamanager/mediadirnotify.h47
-rw-r--r--kioslave/media/mediamanager/medialist.cpp288
-rw-r--r--kioslave/media/mediamanager/medialist.h79
-rw-r--r--kioslave/media/mediamanager/mediamanager.cpp342
-rw-r--r--kioslave/media/mediamanager/mediamanager.desktop141
-rw-r--r--kioslave/media/mediamanager/mediamanager.h90
-rw-r--r--kioslave/media/mediamanager/removablebackend.cpp180
-rw-r--r--kioslave/media/mediamanager/removablebackend.h52
-rw-r--r--kioslave/media/medianotifier/Makefile.am18
-rw-r--r--kioslave/media/medianotifier/medianotifier.cpp312
-rw-r--r--kioslave/media/medianotifier/medianotifier.desktop122
-rw-r--r--kioslave/media/medianotifier/medianotifier.h57
-rw-r--r--kioslave/media/medianotifier/notificationdialog.cpp147
-rw-r--r--kioslave/media/medianotifier/notificationdialog.h56
-rw-r--r--kioslave/media/medianotifier/notificationdialogview.ui117
-rw-r--r--kioslave/media/mimetypes/Makefile.am22
-rw-r--r--kioslave/media/mimetypes/audiocd.desktop66
-rw-r--r--kioslave/media/mimetypes/blankcd.desktop73
-rw-r--r--kioslave/media/mimetypes/blankdvd.desktop73
-rw-r--r--kioslave/media/mimetypes/camera_mounted.desktop69
-rw-r--r--kioslave/media/mimetypes/camera_unmounted.desktop69
-rw-r--r--kioslave/media/mimetypes/cdrom_mounted.desktop85
-rw-r--r--kioslave/media/mimetypes/cdrom_unmounted.desktop86
-rw-r--r--kioslave/media/mimetypes/cdwriter_mounted.desktop86
-rw-r--r--kioslave/media/mimetypes/cdwriter_unmounted.desktop86
-rw-r--r--kioslave/media/mimetypes/dvd_mounted.desktop81
-rw-r--r--kioslave/media/mimetypes/dvd_unmounted.desktop81
-rw-r--r--kioslave/media/mimetypes/dvdvideo.desktop73
-rw-r--r--kioslave/media/mimetypes/floppy5_mounted.desktop85
-rw-r--r--kioslave/media/mimetypes/floppy5_unmounted.desktop85
-rw-r--r--kioslave/media/mimetypes/floppy_mounted.desktop85
-rw-r--r--kioslave/media/mimetypes/floppy_unmounted.desktop85
-rw-r--r--kioslave/media/mimetypes/gphoto2camera.desktop76
-rw-r--r--kioslave/media/mimetypes/hdd_mounted.desktop77
-rw-r--r--kioslave/media/mimetypes/hdd_unmounted.desktop77
-rw-r--r--kioslave/media/mimetypes/nfs_mounted.desktop77
-rw-r--r--kioslave/media/mimetypes/nfs_unmounted.desktop77
-rw-r--r--kioslave/media/mimetypes/removable_mounted.desktop77
-rw-r--r--kioslave/media/mimetypes/removable_unmounted.desktop77
-rw-r--r--kioslave/media/mimetypes/smb_mounted.desktop83
-rw-r--r--kioslave/media/mimetypes/smb_unmounted.desktop84
-rw-r--r--kioslave/media/mimetypes/svcd.desktop50
-rw-r--r--kioslave/media/mimetypes/vcd.desktop50
-rw-r--r--kioslave/media/mimetypes/zip_mounted.desktop85
-rw-r--r--kioslave/media/mimetypes/zip_unmounted.desktop85
-rw-r--r--kioslave/media/mounthelper/Makefile.am12
-rw-r--r--kioslave/media/mounthelper/kio_media_mounthelper.cpp209
-rw-r--r--kioslave/media/mounthelper/kio_media_mounthelper.h49
-rw-r--r--kioslave/media/propsdlgplugin/Makefile.am12
-rw-r--r--kioslave/media/propsdlgplugin/media_propsdlgplugin.desktop102
-rw-r--r--kioslave/media/propsdlgplugin/propertiespage.cpp217
-rw-r--r--kioslave/media/propsdlgplugin/propertiespage.h46
-rw-r--r--kioslave/media/propsdlgplugin/propertiespagegui.ui387
-rw-r--r--kioslave/media/propsdlgplugin/propertiespagegui.ui.h22
-rw-r--r--kioslave/media/propsdlgplugin/propsdlgshareplugin.cpp100
-rw-r--r--kioslave/media/propsdlgplugin/propsdlgshareplugin.h44
-rw-r--r--kioslave/media/services/Makefile.am3
-rw-r--r--kioslave/media/services/media_eject.desktop90
-rw-r--r--kioslave/media/services/media_mount.desktop87
-rw-r--r--kioslave/media/services/media_safelyremove.desktop75
-rw-r--r--kioslave/media/services/media_unmount.desktop87
-rw-r--r--kioslave/media/testmedia.cpp69
-rw-r--r--kioslave/media/testmedia.h34
120 files changed, 13552 insertions, 0 deletions
diff --git a/kioslave/media/Makefile.am b/kioslave/media/Makefile.am
new file mode 100644
index 000000000..e727fc4a3
--- /dev/null
+++ b/kioslave/media/Makefile.am
@@ -0,0 +1,36 @@
+if include_media_halbackend
+PROPSDLGPLUGINDIR = propsdlgplugin
+endif
+
+SUBDIRS = libmediacommon . mediamanager medianotifier mounthelper \
+ kfile-plugin kcmodule mimetypes services $(PROPSDLGPLUGINDIR)
+
+INCLUDES = -I$(srcdir)/libmediacommon $(all_includes)
+METASOURCES = AUTO
+
+kde_module_LTLIBRARIES = kio_media.la
+
+kio_media_la_SOURCES = dummy.cpp
+kio_media_la_LIBADD = libkiomedia.la libmediacommon/libmediacommon.la $(LIB_KIO)
+kio_media_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) -no-undefined
+
+dummy.cpp:
+ echo > dummy.cpp
+
+kde_services_DATA = media.protocol
+
+noinst_LTLIBRARIES = libkiomedia.la
+libkiomedia_la_SOURCES = kio_media.cpp mediaimpl.cpp mediaimpl.skel
+
+check_PROGRAMS = testmedia
+testmedia_SOURCES = testmedia.cpp
+testmedia_LDADD = libkiomedia.la $(LIB_KIO)
+testmedia_LDFLAGS = $(all_libraries)
+
+## TODO in unsermake: TESTS = testmedia
+check: testmedia
+ ./testmedia
+
+messages: rc.cpp
+ $(EXTRACTRC) propsdlgplugin/propertiespagegui.ui >> rc.cpp
+ $(XGETTEXT) *.cpp *.h kfile-plugin/*.cpp libmediacommon/*.cpp mediamanager/*.cpp mounthelper/*.cpp propsdlgplugin/*.cpp -o $(podir)/kio_media.pot
diff --git a/kioslave/media/configure.in.in b/kioslave/media/configure.in.in
new file mode 100644
index 000000000..81c8f2640
--- /dev/null
+++ b/kioslave/media/configure.in.in
@@ -0,0 +1,184 @@
+########### Check for linux/cdrom.h
+
+AC_CHECK_HEADER(linux/cdrom.h,
+[
+ AC_DEFINE_UNQUOTED([COMPILE_LINUXCDPOLLING], 1, [media linux cd polling compilation])
+ LINUXCDPOLLING=yes
+ AC_SUBST(LINUXCDPOLLING)
+])
+
+
+AC_ARG_WITH(hal,AC_HELP_STRING([--with-hal],[Enable HAL support [default=check]]),[hal_test="$withval"],[hal_test="yes"])
+
+if test "x$hal_test" = "xyes" ; then
+
+########### Check for the HAL
+ AC_MSG_CHECKING(for the HAL)
+
+ hal_inc=NOTFOUND
+ hal_lib=NOTFOUND
+ hal=NOTFOUND
+
+ search_incs="$kde_includes $kde_extra_includes /usr/include /usr/include/hal /usr/local/include /usr/local/include/hal"
+ AC_FIND_FILE(libhal.h libhal-storage.h, $search_incs, hal_incdir)
+
+ if test -r $hal_incdir/libhal.h && test -r $hal_incdir/libhal-storage.h && grep LibHalVolume $hal_incdir/libhal-storage.h > /dev/null 2>&1; then
+ HAL_INCS="-I$hal_incdir"
+ hal_inc=FOUND
+ fi
+
+ search_libs="$kde_libraries $kde_extra_libs /usr/lib$kdelibsuff /usr/local/lib$kdelibsuff"
+ AC_FIND_FILE(libhal.so libhal-storage.so, $search_libs, hal_libdir)
+
+ if test -r $hal_libdir/libhal.so && test -r $hal_libdir/libhal-storage.so ; then
+ HAL_LIBS="-L$hal_libdir -lhal -lhal-storage"
+ hal_lib=FOUND
+ fi
+
+ if test "$hal_inc" != FOUND || test "$hal_lib" != FOUND; then
+ KDE_PKG_CHECK_MODULES( HAL, hal > 0.5, [ HAL_INCS=$HAL_CFLAGS; hal_inc=FOUND; hal_lib=FOUND; ] , AC_MSG_RESULT(Nothing found on PKG_CONFIG_PATH) )
+ fi
+
+ if test "$hal_inc" = FOUND && test "$hal_lib" = FOUND ; then
+ AC_MSG_RESULT(headers $HAL_INCS libraries $HAL_LIBS)
+ hal=FOUND
+ else
+ AC_MSG_RESULT(searched but not found)
+ fi
+
+
+ AC_SUBST(HAL_INCS)
+ AC_SUBST(HAL_LIBS)
+
+
+########### Check for DBus
+
+ AC_MSG_CHECKING(for DBus)
+
+ dbus_inc=NOTFOUND
+ dbus_lib=NOTFOUND
+ dbus=NOTFOUND
+
+ search_incs="$kde_includes $kde_extra_includes /usr/include /usr/include/dbus-1.0 /usr/local/include /usr/local/include/dbus-1.0"
+ AC_FIND_FILE(dbus/dbus.h, $search_incs, dbus_incdir)
+
+ search_incs_arch_deps="$kde_includes $kde_extra_includes /usr/lib$kdelibsuff/dbus-1.0/include /usr/local/lib$kdelibsuff/dbus-1.0/include"
+ AC_FIND_FILE(dbus/dbus-arch-deps.h, $search_incs_arch_deps, dbus_incdir_arch_deps)
+
+ if test -r $dbus_incdir/dbus/dbus.h && test -r $dbus_incdir_arch_deps/dbus/dbus-arch-deps.h ; then
+ DBUS_INCS="-I$dbus_incdir -I$dbus_incdir_arch_deps"
+ dbus_inc=FOUND
+ fi
+
+ search_libs="$kde_libraries $kde_extra_libs /usr/lib$kdelibsuff /usr/local/lib$kdelibsuff"
+ AC_FIND_FILE(libdbus-1.so, $search_libs, dbus_libdir)
+
+ if test -r $dbus_libdir/libdbus-1.so ; then
+ DBUS_LIBS="-L$dbus_libdir -ldbus-1"
+ dbus_lib=FOUND
+ fi
+
+ if test $dbus_inc != FOUND || test $dbus_lib != FOUND ; then
+ KDE_PKG_CHECK_MODULES( DBUS, "dbus-1", [ DBUS_INCS=$DBUS_CFLAGS; dbus_inc=FOUND; dbus_lib=FOUND; ] , AC_MSG_RESULT( Nothing found on PKG_CONFIG_PATH ) )
+ fi
+
+ dbus_bus_var=`pkg-config --variable=system_bus_default_address dbus-1 2>/dev/null`
+ if test -z "$dbus_bus_var"; then
+ dbus_bus_var="unix:path=/var/run/dbus/system_bus_socket"
+ fi
+ AC_DEFINE_UNQUOTED(DBUS_SYSTEM_BUS, "$dbus_bus_var", [Define the unix domain path for dbus system bus])
+
+ if test $dbus_inc = FOUND && test $dbus_lib = FOUND ; then
+ AC_MSG_RESULT(headers $DBUS_INCS libraries $DBUS_LIBS)
+ dbus=FOUND
+ else
+ AC_MSG_RESULT(searched but not found)
+ fi
+
+ AC_SUBST(DBUS_INCS)
+ AC_SUBST(DBUS_LIBS)
+
+########### Check for DBus-Qt3 bindings
+
+ AC_MSG_CHECKING(for DBus-Qt3 bindings)
+
+ dbusqt_inc=NOTFOUND
+ dbusqt_lib=NOTFOUND
+ dbusqt=NOTFOUND
+
+ search_incs="$kde_includes $kde_extra_includes /usr/include /usr/include/dbus-1.0 /usr/local/include /usr/local/include/dbus-1.0"
+ AC_FIND_FILE(dbus/connection.h, $search_incs, dbusqt_incdir)
+
+ if test -r $dbusqt_incdir/dbus/connection.h ; then
+ have_qt_patch=0
+ grep dbus_connection_setup_with_qt_main $dbusqt_incdir/dbus/connection.h \
+ > /dev/null 2>&1 && have_qt_patch=1
+ if test $have_qt_patch = 1 ; then
+ DBUSQT_INCS="-I$dbusqt_incdir"
+ dbusqt_inc=FOUND
+ fi
+ fi
+
+ search_libs="$kde_libraries $kde_extra_libs /usr/lib$kdelibsuff /usr/local/lib$kdelibsuff"
+ AC_FIND_FILE(libdbus-qt-1.so, $search_libs, dbusqt_libdir)
+
+ if test -r $dbusqt_libdir/libdbus-qt-1.so ; then
+ DBUSQT_LIBS="-L$dbusqt_libdir -ldbus-qt-1"
+ dbusqt_lib=FOUND
+ fi
+
+ if test $dbusqt_inc != FOUND || test $dbusqt_lib != FOUND ; then
+
+ search_incs="`pkg-config --cflags dbus-1 |sed 's/-I//g'`"
+ AC_FIND_FILE(dbus/connection.h, $search_incs, dbusqt_incdir)
+ if test -r $dbusqt_incdir/dbus/connection.h ; then
+ have_qt_patch=0
+ grep dbus_connection_setup_with_qt_main $dbusqt_incdir/dbus/connection.h \
+ > /dev/null 2>&1 && have_qt_patch=1
+ if test $have_qt_patch = 1 ; then
+ DBUSQT_INCS="-I$dbusqt_incdir"
+ dbusqt_inc=FOUND
+ fi
+ fi
+
+ search_libs="`pkg-config --libs dbus-1 --libs-only-L | sed 's/-L//g'`"
+ AC_FIND_FILE(libdbus-qt-1.so, $search_libs, dbusqt_libdir)
+
+ if test -r $dbusqt_libdir/libdbus-qt-1.so ; then
+ DBUSQT_LIBS="-L$dbusqt_libdir -ldbus-qt-1"
+ dbusqt_lib=FOUND
+ fi
+
+ fi
+
+
+ if test $dbusqt_inc = FOUND && test $dbusqt_lib = FOUND ; then
+ AC_MSG_RESULT(headers $dbusqt_incdir libraries $dbusqt_libdir)
+ dbusqt=FOUND
+ else
+ AC_MSG_RESULT(searched but not found)
+ fi
+
+ AC_SUBST(DBUSQT_INCS)
+ AC_SUBST(DBUSQT_LIBS)
+fi
+
+########### Check if media HAL backend sould be compiled
+
+AC_MSG_CHECKING(if the HAL backend for media:/ should be compiled)
+
+HALBACKEND=no
+if test "x$hal" = "xFOUND" && test "x$dbus" = "xFOUND" && test "x$dbusqt" = "xFOUND" ; then
+ AC_DEFINE_UNQUOTED([COMPILE_HALBACKEND],1, [media HAL backend compilation])
+ HALBACKEND=yes
+ AC_SUBST(HALBACKEND)
+ AC_MSG_RESULT(yes)
+else
+ AC_MSG_RESULT(no)
+fi
+
+AM_CONDITIONAL(include_media_linuxcdpolling, test "$LINUXCDPOLLING" = "yes")
+AM_CONDITIONAL(include_media_halbackend, test "$HALBACKEND" = yes)
+
+AC_CHECK_FUNCS(statvfs)
+
diff --git a/kioslave/media/contrib/README b/kioslave/media/contrib/README
new file mode 100644
index 000000000..8f6041578
--- /dev/null
+++ b/kioslave/media/contrib/README
@@ -0,0 +1,18 @@
+Those scripts are an example on how to allow media:/ to use
+hotplugging events if you don't use HAL. They're targeting
+"Linux 2.6 + hotplug + udev" platforms, but we can surely make
+something equivalent for Linux 2.4, FreeBSD...
+
+They are just examples, the packagers will surely develop their
+own version (I'm currently using them on Debian Sid, Linux 2.6.9
+though).
+
+1) mediamanager_usbstorage.dev
+This file only needs to be copied to /etc/dev.d/default
+
+2) usbcam
+This one is a bit more complicated to install.
+The file must be copied into /etc/hotplug/usb and the file
+/etc/hotplug/usb/usbcam.usermap must exists (you can use
+libgphoto2's print-usb-usermap command to create it)
+
diff --git a/kioslave/media/contrib/mediamanager_usbstorage.dev b/kioslave/media/contrib/mediamanager_usbstorage.dev
new file mode 100755
index 000000000..d12a3e687
--- /dev/null
+++ b/kioslave/media/contrib/mediamanager_usbstorage.dev
@@ -0,0 +1,108 @@
+#!/bin/sh
+# /etc/dev.d/default/mediamanager_usbstorage.dev
+# Notify all KDE sessions (thanks to the mediamanager) that a new
+# usb_storage device appeared or disappeared
+#
+
+# to debug this script, uncomment the next line and see /tmp/mediamanager_usbstorage.debug after execution
+#DEBUG=1
+
+# exit immediately if /usr/bin/ is not yet available (during boot if /usr is a separate partition)
+/bin/ls -d /usr/bin/ >/dev/null 2>&1 || exit
+
+DEBUGOUT=/tmp/mediamanager_usbstorage.debug.$$
+if [ "$DEBUG" = "1" -a -z "$2" ]; then
+ echo "executing $0 $@" > $DEBUGOUT
+ echo "with the following environment variables:" >> $DEBUGOUT
+ env >> $DEBUGOUT
+ echo "----" >> $DEBUGOUT
+ sh -x $0 $@ debug >> $DEBUGOUT 2>&1
+ exit
+fi
+
+# we only manage block devices
+if [ "$1" != "block" ]; then exit; fi
+
+# we only manage usb_storage devices
+if [ "$ACTION" = "add" ]; then
+ device="`ls /sys$DEVPATH/../device/../../../ 2> /dev/NULL | grep ':' | head -1`"
+ if [ -z "$device" -o ! -e /sys/bus/usb/drivers/usb-storage/$device ]; then
+ # The behavior is not the same for every kernel it seems.
+ # Testing the driver/ directory just in case.
+ device="`ls /sys$DEVPATH/../device/../../../driver 2> /dev/NULL | grep ':' | head -1`"
+ if [ -z "$device" -o ! -e /sys/bus/usb/drivers/usb-storage/$device ]; then
+ exit
+ fi
+ fi
+fi
+
+# functions for syslog
+LOGGER="logger -t `basename $0`[$$] -p user.notice"
+write_syslog () {
+ echo ${@} | $LOGGER
+}
+
+# be sure the drivers are loaded
+/sbin/modprobe -q usb_storage
+/sbin/modprobe -q vfat
+
+# create the FSH required /media directory
+# See: http://www.pathname.com/fhs/pub/fhs-2.3.html#MEDIAMOUNTPOINT
+MNT=media
+if [ ! -d /$MNT ]; then
+ mkdir /$MNT
+ write_syslog "Created the /$MNT directory"
+fi
+
+# we need DEVPATH, DEVNAME and ACTION, so we warn the user that executes this script by hand
+if [ -z "$DEVPATH" -a -z "$DEVNAME" -a -z "$ACTION" ]; then
+ echo
+ echo "This script must be called by udevd because it needs the following environment variables: DEVPATH, DEVNAME, ACTION"
+ echo "So you must copy this script as /etc/dev.d/default/updfstab-2.6.dev and set it executable"
+ echo "See: http://www.kernel.org/pub/linux/utils/kernel/hotplug/RFC-dev.d"
+ echo
+ exit
+fi
+
+# if $DEVPATH/device exists, we are a device, not a partition, so exit
+if [ -d /sys${DEVPATH}/device ]; then exit; fi
+
+dcop_users="`ps aux | grep dcopserver | grep -v grep | awk '{print $1}' | sort | uniq`"
+
+# if the current device is being added
+if [ "$ACTION" = "add" ]; then
+ # get partition information
+ partition="/sys${DEVPATH}/../device/../../.."
+ # We check twice again... marvelous random kernel behaviour changes...
+ if [ -e $partition/product ]; then
+ product="`cat $partition/product`"
+ else
+ product="`cat $partition/../product`"
+ fi
+ if [ -e $partition/manufacturer ]; then
+ manufacturer="`cat $partition/manufacturer`"
+ else
+ manufacturer="`cat $partition/../manufacturer`"
+ fi
+
+ write_syslog "Invoking dcop..."
+ write_syslog "kded mediamanager removablePlug $DEVNAME \"$manufacturer $product\""
+
+ method="kded mediamanager removablePlug"
+ for user in $dcop_users ; do
+ dcop --user $user --all-sessions $method $DEVNAME "$manufacturer $product"
+ done
+
+elif [ "$ACTION" = "remove" ]; then
+ write_syslog "Invoking dcop..."
+ write_syslog "kded mediamanager removableUnplug $DEVNAME"
+
+ method="kded mediamanager removableUnplug"
+ for user in $dcop_users ; do
+ dcop --user $user --all-sessions $method $DEVNAME
+ done
+
+ umount $DEVNAME
+fi
+
+
diff --git a/kioslave/media/contrib/usbcam b/kioslave/media/contrib/usbcam
new file mode 100755
index 000000000..85158d96b
--- /dev/null
+++ b/kioslave/media/contrib/usbcam
@@ -0,0 +1,82 @@
+#!/bin/sh
+#
+# /etc/hotplug/usb/usbcam
+#
+# Set up newly plugged in USB camera
+# Notify all KDE sessions (thanks to the mediamanager) that a
+# new camera appeared or disappeared
+
+# to debug this script, uncomment the next line and see /tmp/usbcam.debug after execution
+#DEBUG=1
+
+# exit immediately if /usr/bin/ is not yet available (during boot if /usr is a separate partition)
+/bin/ls -d /usr/bin/ >/dev/null 2>&1 || exit
+
+GROUP=camera
+
+if [ "${ACTION}" = "add" ] && [ -f "${DEVICE}" ]
+then
+ chmod a-rwx "${DEVICE}"
+ chgrp "${GROUP}" "${DEVICE}"
+ chmod ug+rw "${DEVICE}"
+fi
+
+
+DEBUGOUT=/tmp/usbcam.debug.$$
+if [ "$DEBUG" = "1" -a -z "$2" ]; then
+ echo "executing $0 $@" > $DEBUGOUT
+ echo "with the following environment variables:" >> $DEBUGOUT
+ env >> $DEBUGOUT
+ echo "----" >> $DEBUGOUT
+ sh -x $0 $@ debug >> $DEBUGOUT 2>&1
+ exit
+fi
+
+# functions for syslog
+LOGGER="logger -t `basename $0`[$$] -p user.notice"
+write_syslog () {
+ echo ${@} | $LOGGER
+}
+
+if [ -z "$REMOVER" ]; then
+ write_syslog "No remover found"
+ exit
+fi
+
+dcop_users="`ps aux | grep dcopserver | grep -v grep | awk '{print $1}' | sort | uniq`"
+
+# if the current device is being added
+if [ "$ACTION" = "add" ]; then
+ write_syslog "Copying remover..."
+ cp /etc/hotplug/usb/usbcam $REMOVER
+ chmod +x $REMOVER
+ # get camera information
+ camera="/sys${DEVPATH}/.."
+ if [ -e $camera/product ]; then product="`cat $camera/product`"; fi
+ if [ -e $camera/manufacturer ]; then manufacturer="`cat $camera/manufacturer`"; fi
+
+ write_syslog "Invoking dcop..."
+ write_syslog "kded mediamanager removableCamera $DEVICE \"$manufacturer $product\""
+
+ method="kded mediamanager removablePlug"
+ for user in $dcop_users ; do
+ dcop --user $user --all-sessions $method $DEVICE "$manufacturer $product"
+ done
+
+ method="kded mediamanager removableCamera"
+ for user in $dcop_users ; do
+ dcop --user $user --all-sessions $method $DEVICE
+ done
+
+elif [ "$ACTION" = "remove" ]; then
+ write_syslog "Invoking dcop..."
+ write_syslog "kded mediamanager removableUnplug $DEVICE"
+
+ method="kded mediamanager removableUnplug"
+ for user in $dcop_users ; do
+ dcop --user $user --all-sessions $method $DEVICE
+ done
+
+fi
+
+
diff --git a/kioslave/media/dummy.cpp b/kioslave/media/dummy.cpp
new file mode 100644
index 000000000..8b1378917
--- /dev/null
+++ b/kioslave/media/dummy.cpp
@@ -0,0 +1 @@
+
diff --git a/kioslave/media/kcmodule/Makefile.am b/kioslave/media/kcmodule/Makefile.am
new file mode 100644
index 000000000..72f9f385c
--- /dev/null
+++ b/kioslave/media/kcmodule/Makefile.am
@@ -0,0 +1,21 @@
+INCLUDES = -I$(srcdir)/../libmediacommon -I../libmediacommon $(all_includes)
+METASOURCES = AUTO
+
+kde_module_LTLIBRARIES = kcm_media.la
+kcm_media_la_SOURCES = notifiermodule.cpp notifiermoduleview.ui \
+ serviceconfigdialog.cpp serviceview.ui \
+ mimetypelistboxitem.cpp \
+ managermodule.cpp managermoduleview.ui \
+ main.cpp
+
+kcm_media_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries)
+kcm_media_la_LIBADD = ../libmediacommon/libmediacommon.la $(LIB_KIO)
+
+noinst_HEADERS = notifiermodule.h managermodule.h \
+ serviceconfigdialog.h mimetypelistboxitem.h \
+ main.h
+
+xdg_apps_DATA = media.desktop
+
+messages: rc.cpp
+ $(XGETTEXT) *.cpp -o $(podir)/kcmmedia.pot
diff --git a/kioslave/media/kcmodule/main.cpp b/kioslave/media/kcmodule/main.cpp
new file mode 100644
index 000000000..e431e95f8
--- /dev/null
+++ b/kioslave/media/kcmodule/main.cpp
@@ -0,0 +1,103 @@
+/* This file is part of the KDE Project
+ Copyright (c) 2005 Jean-Remy Falleri <jr.falleri@laposte.net>
+ Copyright (c) 2005 Kévin Ottens <ervin ipsquad net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "main.h"
+
+#include <qtabwidget.h>
+#include <qlayout.h>
+
+#include <klocale.h>
+#include <kaboutdata.h>
+#include <kdialog.h>
+
+#include <kgenericfactory.h>
+
+#include "notifiermodule.h"
+#include "managermodule.h"
+
+
+typedef KGenericFactory<MediaModule, QWidget> MediaFactory;
+K_EXPORT_COMPONENT_FACTORY( kcm_media, MediaFactory( "kcmmedia" ) )
+
+
+MediaModule::MediaModule( QWidget *parent, const char *name, const QStringList& )
+ : KCModule(MediaFactory::instance(), parent, name )
+{
+ KGlobal::locale()->insertCatalogue("kio_media");
+ QVBoxLayout *layout = new QVBoxLayout( this, 0, KDialog::spacingHint() );
+ QTabWidget *tab = new QTabWidget( this );
+
+ layout->addWidget( tab );
+
+
+
+ m_notifierModule = new NotifierModule( this, "notifier" );
+ tab->addTab( m_notifierModule, i18n( "&Notifications" ) );
+ connect( m_notifierModule, SIGNAL( changed( bool ) ),
+ this, SLOT( moduleChanged( bool ) ) );
+
+ m_managerModule = new ManagerModule( this, "manager" );
+ tab->addTab( m_managerModule, i18n( "&Advanced" ) );
+ connect( m_managerModule, SIGNAL( changed( bool ) ),
+ this, SLOT( moduleChanged( bool ) ) );
+
+
+
+ KAboutData * about = new KAboutData("kcmmedia",
+ I18N_NOOP("Storage Media"),
+ "0.6",
+ I18N_NOOP("Storage Media Control Panel Module"),
+ KAboutData::License_GPL_V2,
+ I18N_NOOP("(c) 2005 Jean-Remy Falleri"));
+ about->addAuthor("Jean-Remy Falleri", I18N_NOOP("Maintainer"), "jr.falleri@laposte.net");
+ about->addAuthor("Kevin Ottens", 0, "ervin ipsquad net");
+ about->addCredit("Achim Bohnet", I18N_NOOP("Help for the application design"));
+
+ setAboutData( about );
+}
+
+void MediaModule::load()
+{
+ m_notifierModule->load();
+ m_managerModule->load();
+}
+
+void MediaModule::save()
+{
+ m_notifierModule->save();
+ m_managerModule->save();
+}
+
+void MediaModule::defaults()
+{
+ m_notifierModule->defaults();
+ m_managerModule->defaults();
+}
+
+void MediaModule::moduleChanged( bool state )
+{
+ emit changed( state );
+}
+
+QString MediaModule::quickHelp() const
+{
+ return i18n("FIXME : Write me...");
+}
+
+#include "main.moc"
diff --git a/kioslave/media/kcmodule/main.h b/kioslave/media/kcmodule/main.h
new file mode 100644
index 000000000..1ab909527
--- /dev/null
+++ b/kioslave/media/kcmodule/main.h
@@ -0,0 +1,45 @@
+/* This file is part of the KDE Project
+ Copyright (c) 2005 Jean-Remy Falleri <jr.falleri@laposte.net>
+ Copyright (c) 2005 Kvin Ottens <ervin ipsquad net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef _MAIN_H_
+#define _MAIN_H_
+
+#include <kcmodule.h>
+
+class MediaModule : public KCModule
+{
+ Q_OBJECT
+
+public:
+ MediaModule( QWidget *parent, const char *name, const QStringList& );
+
+ virtual void load();
+ virtual void save();
+ virtual void defaults();
+ virtual QString quickHelp() const;
+
+protected slots:
+ void moduleChanged( bool state );
+
+private:
+ KCModule *m_notifierModule;
+ KCModule *m_managerModule;
+};
+
+#endif
diff --git a/kioslave/media/kcmodule/managermodule.cpp b/kioslave/media/kcmodule/managermodule.cpp
new file mode 100644
index 000000000..e5f493d27
--- /dev/null
+++ b/kioslave/media/kcmodule/managermodule.cpp
@@ -0,0 +1,74 @@
+/* This file is part of the KDE Project
+ Copyright (c) 2005 Kvin Ottens <ervin ipsquad net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <config.h>
+
+#include "managermodule.h"
+
+#include <klocale.h>
+#include <dcopref.h>
+#include <qcheckbox.h>
+#include <kdirnotify_stub.h>
+
+#include "managermoduleview.h"
+#include "mediamanagersettings.h"
+
+ManagerModule::ManagerModule( QWidget* parent, const char* name )
+ : KCModule( parent, name )
+{
+ ManagerModuleView *view = new ManagerModuleView( this );
+
+ addConfig( MediaManagerSettings::self(), view );
+
+#ifndef COMPILE_HALBACKEND
+ QString hal_text = view->kcfg_HalBackendEnabled->text();
+ hal_text += " ("+i18n("No support for HAL on this system")+")";
+ view->kcfg_HalBackendEnabled->setText( hal_text );
+#endif
+ view->kcfg_HalBackendEnabled->setEnabled( false );
+
+#ifndef COMPILE_LINUXCDPOLLING
+ QString poll_text = view->kcfg_CdPollingEnabled->text();
+ poll_text += " ("+i18n("No support for CD polling on this system")+")";
+ view->kcfg_CdPollingEnabled->setText( poll_text );
+#endif
+ view->kcfg_CdPollingEnabled->setEnabled( false );
+
+ load();
+}
+
+void ManagerModule::save()
+{
+ KCModule::save();
+
+ //Well... reloadBackends is buggy with HAL, it seems to be linked
+ //to a bug in the unmaintained Qt3 DBUS binding ;-/
+ //DCOPRef mediamanager( "kded", "mediamanager" );
+ //DCOPReply reply = mediamanager.call( "reloadBackends" );
+
+ // So we use this hack instead...
+ DCOPRef kded( "kded", "kded" );
+ kded.call( "unloadModule", "mediamanager" );
+ kded.call( "loadModule", "mediamanager" );
+
+ KDirNotify_stub notifier( "*", "*" );
+ notifier.FilesAdded( "media:/" );
+}
+
+
+#include "managermodule.moc"
diff --git a/kioslave/media/kcmodule/managermodule.h b/kioslave/media/kcmodule/managermodule.h
new file mode 100644
index 000000000..7fa3d649a
--- /dev/null
+++ b/kioslave/media/kcmodule/managermodule.h
@@ -0,0 +1,34 @@
+/* This file is part of the KDE Project
+ Copyright (c) 2005 Kvin Ottens <ervin ipsquad net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef _MANAGERMODULE_H_
+#define _MANAGERMODULE_H_
+
+#include <kcmodule.h>
+
+class ManagerModule : public KCModule
+{
+ Q_OBJECT
+
+public:
+ ManagerModule( QWidget* parent = 0, const char* name = 0);
+
+ void save();
+};
+
+#endif
diff --git a/kioslave/media/kcmodule/managermoduleview.ui b/kioslave/media/kcmodule/managermoduleview.ui
new file mode 100644
index 000000000..598718389
--- /dev/null
+++ b/kioslave/media/kcmodule/managermoduleview.ui
@@ -0,0 +1,72 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>ManagerModuleView</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>ManagerModuleView</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>600</width>
+ <height>480</height>
+ </rect>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>kcfg_HalBackendEnabled</cstring>
+ </property>
+ <property name="text">
+ <string>Enable HAL backend</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Select this if you want to enable the Hardware Abstraction Layer (http://hal.freedesktop.org/wiki/Software/hal) support.</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>kcfg_CdPollingEnabled</cstring>
+ </property>
+ <property name="text">
+ <string>Enable CD polling</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Select this to enable the CD polling.</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>kcfg_AutostartEnabled</cstring>
+ </property>
+ <property name="text">
+ <string>Enable medium application autostart after mount</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Select this if you want to enable application autostart after mounting a device.</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>21</width>
+ <height>360</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+</widget>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/kioslave/media/kcmodule/media.desktop b/kioslave/media/kcmodule/media.desktop
new file mode 100644
index 000000000..c49945253
--- /dev/null
+++ b/kioslave/media/kcmodule/media.desktop
@@ -0,0 +1,197 @@
+[Desktop Entry]
+Type=Application
+#DocPath=
+Icon=system
+Exec=kcmshell media
+
+
+X-KDE-Library=media
+X-KDE-FactoryName=media
+X-KDE-ParentApp=kcontrol
+
+Name=Storage Media
+Name[af]=Stoor Media
+Name[ar]=وسائط التخزين
+Name[be]=Носьбіты
+Name[bg]=Съхраняващи устройства
+Name[bn]=স্টোরেজ মিডিয়া
+Name[bs]=Uređaji za smještaj podataka
+Name[ca]=Suports d'emmagatzematge
+Name[cs]=Úložná zařízení
+Name[csb]=Zôpisowné media
+Name[da]=Opbevaringsmedie
+Name[de]=Speichermedien
+Name[el]=Συσκευές αποθήκευσης
+Name[eo]=Enmemoriga Medio
+Name[es]=Dispositivos de almacenamiento
+Name[et]=Andmekandjad
+Name[eu]=Biltegiratze-euskarria
+Name[fa]=رسانۀ ذخیره‌گاه
+Name[fi]=Tallennusmedia
+Name[fr]=Support de stockage
+Name[fy]=Opslachapparaten
+Name[ga]=Meán Stórais
+Name[gl]=Medios de armacenaxe
+Name[he]=התקנים
+Name[hi]=भंडार मीडिया
+Name[hr]=Mediji za pohranjivanje
+Name[hu]=Tárolóeszközök
+Name[is]=Geymslumiðlar
+Name[it]=Dispositivi di archiviazione
+Name[ja]=記憶メディア
+Name[ka]=მონაცემთა შენახვის მოწყობილობები
+Name[kk]=Жинақтаушы құрылғылар
+Name[km]=ឧបករណ៍​ផ្ទុក
+Name[lt]=Saugojimo įrenginiai
+Name[lv]=Datu nesējs
+Name[mk]=Медиуми за податоци
+Name[ms]=Media Storan
+Name[nb]=Lagringsenheter
+Name[nds]=Spiekermedien
+Name[ne]=भण्डारण मिडिया
+Name[nl]=Opslagapparaten
+Name[nn]=Lagringsmedium
+Name[pa]=ਸਟੋਰੇਜ਼ ਮੀਡਿਆ
+Name[pl]=Urządzenia przechowywania danych
+Name[pt]=Dispositivos de Armazenamento
+Name[pt_BR]=Mídia de Armazenamento
+Name[ro]=Mediu de stocare
+Name[ru]=Устройства хранения данных
+Name[rw]=Uburyo bwo Kubika
+Name[se]=Vurkenmedia
+Name[sk]=Zálohovacie médiá
+Name[sl]=Nosilci za shranjevanje
+Name[sr]=Складишни медијуми
+Name[sr@Latn]=Skladišni medijumi
+Name[sv]=Lagringsmedia
+Name[ta]=சேகரிப்பு ஊடகம்
+Name[tg]=Захирагоҳи маълумот
+Name[th]=สื่อเก็บข้อมูล
+Name[tr]=Depolama Ortamı
+Name[tt]=Saqlawlı Media
+Name[uk]=Пристрої зберігання інформації
+Name[uz]=Saqlash uskunalari
+Name[uz@cyrillic]=Сақлаш ускуналари
+Name[vi]=Ổ chứa Dữ liệu
+Name[wa]=Sopoirts di wårdaedje
+Name[zh_CN]=存储介质
+Name[zh_TW]=儲存媒體
+
+Comment=Configure Storage Media
+Comment[af]=Stel Stoor Media op
+Comment[ar]=إعداد وسائط التخزين
+Comment[be]=Настаўленні носьбітаў
+Comment[bg]=Настройване на устройствата за съхранение на информация
+Comment[bn]=স্টোরেজ মিডিয়া কনফিগার করুন
+Comment[bs]=Podesite prikaz uređaja
+Comment[ca]=Configura els suports d'emmagatzematge
+Comment[cs]=Nastavení úložných médií
+Comment[csb]=Kònfigùracëjô zôpisownëch mediów
+Comment[da]=Opsætning af opbevarelsesmedie
+Comment[de]=Speichermedien einrichten
+Comment[el]=Ρύθμιση μέσων αποθήκευσης
+Comment[eo]=Agordo de enmemoriga medio
+Comment[es]=Configuración de las medios de almacenamiento
+Comment[et]=Salvestusandmekandjate seadistused
+Comment[eu]=Konfiguratu biltegiratze-euskarria
+Comment[fa]=پیکربندی رسانۀ ذخیره‌گاه
+Comment[fi]=Aseta tallennusmedia
+Comment[fr]=Configurer le média de stockage
+Comment[fy]=Opslachmedia ynstelle
+Comment[ga]=Cumraigh Meáin Stórála
+Comment[gl]=Configurar Medios de Armacenaxe
+Comment[he]=שינוי הגדרות מדיות אחסון
+Comment[hr]=Konfiguriranje medija za pohranu
+Comment[hu]=A tárolóeszközök beállítása
+Comment[is]=Stillingar geymslumiðla
+Comment[it]=Configura dispositivi di archiviazione
+Comment[ja]=記憶メディアの設定
+Comment[ka]=შენახვის მედიის გამართვა
+Comment[kk]=Жинақтаушыларды баптау
+Comment[km]=កំណត់​រចនាសម្ព័ន្ធ​ឧបករណ៍​ផ្ទុក
+Comment[lt]=Konfigūruoti saugojimo įrenginius
+Comment[mk]=Конфигурирајте ги медиумите за податоци
+Comment[nb]=Sett opp lagringsmedier
+Comment[nds]=Spiekermedien instellen
+Comment[ne]=भण्डारण मिडिया कन्फिगर गर्नुहोस्
+Comment[nl]=Opslagmedia instellen
+Comment[nn]=Set opp lagringsmedium
+Comment[pa]=ਸਟੋਰੇਜ਼ ਮੀਡਿਆ ਸੰਰਚਨਾ
+Comment[pl]=Konfiguracja nośników danych
+Comment[pt]=Configurar os Suportes de Armazenamento
+Comment[pt_BR]=Configura as mídias de armazenamento
+Comment[ro]=Configurează mediile de stocare
+Comment[ru]=Настройка подключаемых устройств хранения
+Comment[se]=Heivet vurkenmediaid
+Comment[sk]=Nastavenie zálohovacích médií
+Comment[sl]=Nastavitve nosilcev za shranjevanje
+Comment[sr]=Подешавање медијума за складиштење
+Comment[sr@Latn]=Podešavanje medijuma za skladištenje
+Comment[sv]=Anpassa lagringsmedia
+Comment[th]=ตั้งค่าสื่อบันทึก
+Comment[tr]=Depolama Aygıtlarını Yapılandır
+Comment[tt]=Saqlaw Cıhazların Caylaw
+Comment[uk]=Налаштування пристроїв зберігання інформації
+Comment[uz]=Saqlash uskunalarni moslash
+Comment[uz@cyrillic]=Сақлаш ускуналарни мослаш
+Comment[vi]=Cấu hình Ổ lưu trữ Dữ liệu
+Comment[wa]=Apontiaedjes sopoirts di wårdaedje
+Comment[zh_CN]=配置存储介质
+Comment[zh_TW]=設定儲存媒體
+
+Keywords=storage,media,usb,cdrom,device
+Keywords[ar]=تخزين,وسائط,usb,قرص مدمج cdrom,جهاز
+Keywords[be]=Носьбіт,Прылада,storage,media,usb,cdrom,device
+Keywords[bg]=съхранение, информация, компактдиск, устройство, данни, storage, media, usb, cdrom, device
+Keywords[bs]=storage,media,usb,cdrom,device,uređaji,mediji
+Keywords[ca]=emmagatzematge,suport,usb,cdrom,dispositiu
+Keywords[cs]=úložiště,média,USB,CDROM,zařízení
+Keywords[csb]=pòdôwczi,trzëmanié pòdôwków,zôpisowné media,usb,cdrom,ùrządzenié,nëk
+Keywords[da]=opbevaring,medie,usb,cdrom,enhed
+Keywords[de]=Speicher,Medien,Medium,USB,CD-Rom,cdrom,Gerät
+Keywords[el]=αποθήκευση,μέσο,usb,cdrom,συσκευή
+Keywords[eo]=memorigilo,medio,usb,lumdisko,aparato
+Keywords[es]=almacenamiento,medios,usb,cdrom,dispositivo
+Keywords[et]=salvestamine,andmekandja,usb,cd,seade
+Keywords[eu]=biltegiratzea,euskarriak,usb,cdrom,gailua
+Keywords[fa]=ذخیره‌گاه، رسانه، گذرگاه سریال جهانی، دیسک فشرده، دستگاه
+Keywords[fi]=varasto,media,usb,cdrom,laite
+Keywords[fr]=stockage,media,média,medium,usb,cdrom,périphérique
+Keywords[fy]=storage,opslach,media,usb,cd-rom,kompakt-skiif,device,apparaat,mp3-speler,usb-stick,geheugenkaart
+Keywords[ga]=stóráil,stóras,meáin,meán,usb,cdrom,dlúthdhiosca,gléas
+Keywords[gl]=armacenaxe,medios,usb,cdrom,dispositivo
+Keywords[he]=storage,media,usb,cdrom,device,מדיה,התקן,סידירום,תקליטור
+Keywords[hr]=storage,media,usb,cdrom,device,pohrana,snimanje,mediji,uređaj
+Keywords[hu]=tároló,adathordozó,USB,CD-ROM,eszköz
+Keywords[is]=geymsla,miðill,usb,cdrom,tæki
+Keywords[it]=storage,media,usb,cdrom,dispositivi,dvd,penna usb,memory stick,stick
+Keywords[ja]=記憶,メディア,usb,cdrom,デバイス
+Keywords[km]=ឧបករណ៍​ផ្ទុក, usb,ស៊ីឌីរ៉ូម,ឧបករណ៍
+Keywords[lt]=storage,media,usb,cdrom,device,saugojimas,media,įrenginiai,usb
+Keywords[mk]=storage,media,usb,cdrom,device,медиуми,усб,цдром,уред
+Keywords[nb]=lagring,media,usb,CD-spiller,CD-ROM,enheter,minnepinner,harddisker,HD,eksterne harddisker,zip-disker
+Keywords[nds]=Spieker,Medien,USB,CDROM,Reedschap
+Keywords[ne]=भण्डारण, मिडिया,usb,cdrom, यन्त्र
+Keywords[nl]=storage,opslag,media,usb,cd-rom,device,apparaat,mp3-speler,usb-stick,geheugenkaart
+Keywords[nn]=lagring,media,usb,CD-spiller,CD-ROM,einingar,minnepinnar,harddiskar,HD,eksterne harddiskar,zip-diskar
+Keywords[pa]=ਸਟੋਰੇਜ਼,ਮੀਡਿਆ,ਜੰਤਰ,usb,cdrom
+Keywords[pl]=dane,przechowywanie danych,nośnik danych,nośniki danych,usb,cdrom,urządzenie
+Keywords[pt]=armazenamento,discos,usb,cdrom,dispositivo
+Keywords[pt_BR]=armazenamento,mídia,usb,cd-rom,device,dispositivo
+Keywords[ro]=stocare,mediu,usb,cdrom,dispozitiv
+Keywords[ru]=storage,media,usb,cdrom,device,устройство хранения
+Keywords[sl]=shranjevanje,nosilec,usb,cdrom,naprava
+Keywords[sr]=storage,media,usb,cdrom,device,складиштење,медијум,уређај
+Keywords[sr@Latn]=storage,media,usb,cdrom,device,skladištenje,medijum,uređaj
+Keywords[sv]=lagring,media,usb,cdrom,enhet
+Keywords[th]=ที่เก็บข้อมูล,สื่อ,ยูเอสบี,,ซีดีรอม,อุปกรณ์
+Keywords[tr]=depolama,ortam,usb,cdrom,device
+Keywords[uk]=зберігання,носій,медіа,usb,cdrom,пристрій
+Keywords[uz]=saqlash uskunasi,usb,cdrom,kompakt-disk
+Keywords[uz@cyrillic]=сақлаш ускунаси,usb,cdrom,компакт-диск
+Keywords[vi]=lưu trữ,ổ,usb,cdrom,thiết bị
+Keywords[wa]=wårdaedje,media,usb,cdrom,device,éndjin
+Keywords[zh_CN]=storage,media,usb,cdrom,device,存储,介质,设备
+Keywords[zh_TW]=storage,media,usb,cdrom,device,儲存,媒體,光碟機,裝置
+
+Categories=Qt;KDE;X-KDE-settings-peripherals;
diff --git a/kioslave/media/kcmodule/mimetypelistboxitem.cpp b/kioslave/media/kcmodule/mimetypelistboxitem.cpp
new file mode 100644
index 000000000..86460ed88
--- /dev/null
+++ b/kioslave/media/kcmodule/mimetypelistboxitem.cpp
@@ -0,0 +1,35 @@
+/* This file is part of the KDE Project
+ Copyright (c) 2005 Jean-Remy Falleri <jr.falleri@laposte.net>
+ Copyright (c) 2005 Kévin Ottens <ervin ipsquad net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "mimetypelistboxitem.h"
+
+#include <kmimetype.h>
+
+MimetypeListBoxItem::MimetypeListBoxItem(const QString &mimetype, QListBox *parent)
+ : QListBoxText(parent), m_mimetype(mimetype)
+{
+ KMimeType::Ptr mime = KMimeType::mimeType( mimetype );
+ setText( mime->comment() );
+}
+
+const QString &MimetypeListBoxItem::mimetype() const
+{
+ return m_mimetype;
+}
+
diff --git a/kioslave/media/kcmodule/mimetypelistboxitem.h b/kioslave/media/kcmodule/mimetypelistboxitem.h
new file mode 100644
index 000000000..fee215ecf
--- /dev/null
+++ b/kioslave/media/kcmodule/mimetypelistboxitem.h
@@ -0,0 +1,37 @@
+/* This file is part of the KDE Project
+ Copyright (c) 2005 Jean-Remy Falleri <jr.falleri@laposte.net>
+ Copyright (c) 2005 Kvin Ottens <ervin ipsquad net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef _MIMETYPELISTBOXITEM_H_
+#define _MIMETYPELISTBOXITEM_H_
+
+#include <qlistbox.h>
+#include <qstring.h>
+
+class MimetypeListBoxItem : public QListBoxText
+{
+public:
+ MimetypeListBoxItem(const QString &mimetype, QListBox *parent);
+
+ const QString &mimetype() const;
+
+private:
+ QString m_mimetype;
+};
+
+#endif
diff --git a/kioslave/media/kcmodule/notifiermodule.cpp b/kioslave/media/kcmodule/notifiermodule.cpp
new file mode 100644
index 000000000..015d7396a
--- /dev/null
+++ b/kioslave/media/kcmodule/notifiermodule.cpp
@@ -0,0 +1,230 @@
+/* This file is part of the KDE Project
+ Copyright (c) 2005 Jean-Remy Falleri <jr.falleri@laposte.net>
+ Copyright (c) 2005 Kévin Ottens <ervin ipsquad net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "notifiermodule.h"
+
+#include <klocale.h>
+
+#include <qlayout.h>
+#include <kcombobox.h>
+#include <kpushbutton.h>
+#include <kstdguiitem.h>
+
+#include "notifiersettings.h"
+#include "serviceconfigdialog.h"
+#include "actionlistboxitem.h"
+#include "mimetypelistboxitem.h"
+
+NotifierModule::NotifierModule(QWidget *parent, const char *name)
+ : KCModule(parent, name)
+{
+ QBoxLayout *layout = new QVBoxLayout( this, 0, KDialog::spacingHint() );
+
+ m_view = new NotifierModuleView( this );
+ layout->addWidget( m_view );
+
+ m_view->addButton->setGuiItem( KStdGuiItem::add() );
+ m_view->editButton->setGuiItem( KStdGuiItem::properties() );
+ m_view->deleteButton->setGuiItem( KStdGuiItem::del() );
+
+ m_view->mimetypesCombo->insertItem( i18n("All Mime Types") );
+
+ QStringList mimetypes = m_settings.supportedMimetypes();
+
+ QStringList::iterator it = mimetypes.begin();
+ QStringList::iterator end = mimetypes.end();
+
+ for ( ; it!=end; ++it )
+ {
+ new MimetypeListBoxItem( *it, m_view->mimetypesCombo->listBox() );
+ }
+
+ updateListBox();
+
+ connect( m_view->mimetypesCombo, SIGNAL( activated(int) ),
+ this, SLOT( slotMimeTypeChanged(int) ) );
+ connect( m_view->actionsList, SIGNAL( selectionChanged(QListBoxItem*) ),
+ this, SLOT( slotActionSelected(QListBoxItem*) ) );
+ connect( m_view->addButton, SIGNAL( clicked() ),
+ this, SLOT( slotAdd() ) );
+ connect( m_view->editButton, SIGNAL( clicked() ),
+ this, SLOT( slotEdit() ) );
+ connect( m_view->deleteButton, SIGNAL( clicked() ),
+ this, SLOT( slotDelete() ) );
+ connect( m_view->toggleAutoButton, SIGNAL( clicked() ),
+ this, SLOT( slotToggleAuto() ) );
+}
+
+NotifierModule::~NotifierModule()
+{
+}
+
+void NotifierModule::load()
+{
+ m_settings.reload();
+ slotMimeTypeChanged( m_view->mimetypesCombo->currentItem() );
+}
+
+void NotifierModule::save()
+{
+ m_settings.save();
+}
+
+void NotifierModule::defaults()
+{
+ m_settings.clearAutoActions();
+ slotMimeTypeChanged( m_view->mimetypesCombo->currentItem() );
+}
+
+void NotifierModule::updateListBox()
+{
+ m_view->actionsList->clear();
+ slotActionSelected( 0L );
+
+ QValueList<NotifierAction*> services;
+ if ( m_mimetype.isEmpty() )
+ {
+ services = m_settings.actions();
+ }
+ else
+ {
+ services = m_settings.actionsForMimetype( m_mimetype );
+ }
+
+ QValueList<NotifierAction*>::iterator it;
+
+ for ( it = services.begin(); it != services.end(); ++it )
+ {
+ new ActionListBoxItem( *it, m_mimetype, m_view->actionsList );
+ }
+}
+
+void NotifierModule::slotActionSelected(QListBoxItem *item)
+{
+ NotifierAction *action = 0L;
+
+ if ( item!=0L )
+ {
+ ActionListBoxItem *action_item
+ = static_cast<ActionListBoxItem*>(item);
+ action = action_item->action();
+ }
+
+ bool isWritable = action!=0L && action->isWritable();
+ m_view->deleteButton->setEnabled( isWritable );
+ m_view->editButton->setEnabled( isWritable );
+ m_view->addButton->setEnabled( TRUE );
+ m_view->toggleAutoButton->setEnabled( action!=0L && !m_mimetype.isEmpty() );
+}
+
+void NotifierModule::slotMimeTypeChanged(int index)
+{
+ if ( index == 0 )
+ {
+ m_mimetype = QString();
+ }
+ else
+ {
+ QListBoxItem *item = m_view->mimetypesCombo->listBox()->item( index );
+ MimetypeListBoxItem *mime_item
+ = static_cast<MimetypeListBoxItem*>( item );
+ m_mimetype = mime_item->mimetype();
+ }
+
+ updateListBox();
+}
+
+void NotifierModule::slotAdd()
+{
+ NotifierServiceAction *action = new NotifierServiceAction();
+ ServiceConfigDialog dialog(action, m_settings.supportedMimetypes(), this);
+
+ int value = dialog.exec();
+
+ if ( value == QDialog::Accepted )
+ {
+ m_settings.addAction( action );
+ updateListBox();
+ emit changed( true );
+ }
+ else
+ {
+ delete action;
+ }
+}
+
+void NotifierModule::slotEdit()
+{
+ ActionListBoxItem *action_item
+ = static_cast<ActionListBoxItem*>(m_view->actionsList->selectedItem());
+
+ NotifierServiceAction * action = dynamic_cast<NotifierServiceAction*>( action_item->action() );
+ if ( action )
+ {
+ ServiceConfigDialog dialog(action, m_settings.supportedMimetypes(), this);
+
+ int value = dialog.exec();
+
+ if ( value == QDialog::Accepted )
+ {
+ updateListBox();
+ emit changed( true );
+ }
+ }
+}
+
+void NotifierModule::slotDelete()
+{
+ ActionListBoxItem *action_item
+ = static_cast<ActionListBoxItem*>(m_view->actionsList->selectedItem());
+
+ NotifierServiceAction *action;
+ action = dynamic_cast<NotifierServiceAction*>( action_item->action() );
+ if ( action )
+ {
+ m_settings.deleteAction( action );
+ updateListBox();
+ emit changed( true );
+ }
+}
+
+void NotifierModule::slotToggleAuto()
+{
+ ActionListBoxItem *action_item
+ = static_cast<ActionListBoxItem*>( m_view->actionsList->selectedItem() );
+ NotifierAction *action = action_item->action();
+
+ int index = m_view->actionsList->index( action_item );
+
+ if ( action->autoMimetypes().contains( m_mimetype ) )
+ {
+ m_settings.resetAutoAction( m_mimetype );
+ }
+ else
+ {
+ m_settings.setAutoAction( m_mimetype, action );
+ }
+
+ updateListBox();
+ emit changed( true );
+
+ m_view->actionsList->setSelected( index, true );
+}
+
+#include "notifiermodule.moc"
diff --git a/kioslave/media/kcmodule/notifiermodule.h b/kioslave/media/kcmodule/notifiermodule.h
new file mode 100644
index 000000000..6c71df51f
--- /dev/null
+++ b/kioslave/media/kcmodule/notifiermodule.h
@@ -0,0 +1,57 @@
+/* This file is part of the KDE Project
+ Copyright (c) 2005 Jean-Remy Falleri <jr.falleri@laposte.net>
+ Copyright (c) 2005 Kvin Ottens <ervin ipsquad net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef _NOTIFIERMODULE_H_
+#define _NOTIFIERMODULE_H_
+
+#include <kcmodule.h>
+
+#include "notifiersettings.h"
+#include "notifiermoduleview.h"
+
+class NotifierModule : public KCModule
+{
+ Q_OBJECT
+
+public:
+ NotifierModule( QWidget* parent = 0, const char* name = 0);
+ ~NotifierModule();
+
+ void load();
+ void save();
+ void defaults();
+
+private slots:
+ void slotAdd();
+ void slotDelete();
+ void slotEdit();
+ void slotToggleAuto();
+
+ void slotActionSelected( QListBoxItem * item );
+ void slotMimeTypeChanged( int index );
+
+private:
+ void updateListBox();
+
+ QString m_mimetype;
+ NotifierSettings m_settings;
+ NotifierModuleView *m_view;
+};
+
+#endif
diff --git a/kioslave/media/kcmodule/notifiermoduleview.ui b/kioslave/media/kcmodule/notifiermoduleview.ui
new file mode 100644
index 000000000..87edc0f36
--- /dev/null
+++ b/kioslave/media/kcmodule/notifiermoduleview.ui
@@ -0,0 +1,171 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>NotifierModuleView</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>NotifierModuleView</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>600</width>
+ <height>480</height>
+ </rect>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>layout4</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout2</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>mediumType</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Medium types:</string>
+ </property>
+ </widget>
+ <widget class="KComboBox">
+ <property name="name">
+ <cstring>mimetypesCombo</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Here is the list of the available types of medium which can be monitored. You can filter the available actions by selecting a type of medium. If you want to see all the actions, select "All Mime Types".</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout3</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget" row="0" column="1">
+ <property name="name">
+ <cstring>layout1</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>addButton</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Add...</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click here to add an action.</string>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>deleteButton</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Delete</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click here to delete the selected action if possible.</string>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>editButton</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Edit...</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click here to edit the selected action if possible.</string>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>toggleAutoButton</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Toggle as Auto Action</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click here to perform this action automatically on detection of the selected medium type (this option is disabled when "All Mime Types" is selected).</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <spacer row="1" column="1">
+ <property name="name">
+ <cstring>buttonSpacer</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>70</width>
+ <height>101</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="KListBox" row="0" column="0" rowspan="2" colspan="1">
+ <property name="name">
+ <cstring>actionsList</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Here is the list of the available actions. You can modify them by using the buttons on your right.</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </vbox>
+ </widget>
+ </grid>
+</widget>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>kcombobox.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>klistbox.h</includehint>
+</includehints>
+</UI>
diff --git a/kioslave/media/kcmodule/serviceconfigdialog.cpp b/kioslave/media/kcmodule/serviceconfigdialog.cpp
new file mode 100644
index 000000000..1a127d12b
--- /dev/null
+++ b/kioslave/media/kcmodule/serviceconfigdialog.cpp
@@ -0,0 +1,151 @@
+/* This file is part of the KDE Project
+ Copyright (c) 2005 Jean-Remy Falleri <jr.falleri@laposte.net>
+ Copyright (c) 2005 Kévin Ottens <ervin ipsquad net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "serviceconfigdialog.h"
+
+#include <klocale.h>
+#include <klineedit.h>
+#include <kactionselector.h>
+#include <kicondialog.h>
+#include <qlistbox.h>
+#include <kservice.h>
+#include <kopenwith.h>
+#include <kpushbutton.h>
+#include <kiconloader.h>
+#include <qpixmap.h>
+#include <qiconset.h>
+
+
+#include "mimetypelistboxitem.h"
+
+ServiceConfigDialog::ServiceConfigDialog(NotifierServiceAction *action,
+ const QStringList &mimetypesList,
+ QWidget* parent, const char* name)
+ : KDialogBase(parent, name, true, i18n("Edit Service"), Ok|Cancel, Ok, true),
+ m_action(action)
+{
+ m_view = new ServiceView(this);
+
+ m_view->iconButton->setIcon( m_action->iconName() );
+ m_view->labelEdit->setText( m_action->label() );
+ m_view->commandEdit->setText( m_action->service().m_strExec );
+
+ QIconSet iconSet = SmallIconSet("configure");
+ QPixmap pixMap = iconSet.pixmap( QIconSet::Small, QIconSet::Normal );
+ m_view->commandButton->setIconSet( iconSet );
+ m_view->commandButton->setFixedSize( pixMap.width()+8, pixMap.height()+8 );
+
+ m_iconChanged = false;
+
+ QStringList all_mimetypes = mimetypesList;
+ QStringList action_mimetypes = action->mimetypes();
+
+ QStringList::iterator it = all_mimetypes.begin();
+ QStringList::iterator end = all_mimetypes.end();
+
+ for ( ; it!=end; ++it )
+ {
+ QListBox *list;
+
+ if ( action_mimetypes.contains( *it ) )
+ {
+ list = m_view->mimetypesSelector->selectedListBox();
+ }
+ else
+ {
+ list = m_view->mimetypesSelector->availableListBox();
+ }
+
+ new MimetypeListBoxItem( *it, list );
+ }
+
+ setMainWidget(m_view);
+ setCaption( m_action->label() );
+
+ connect( m_view->iconButton, SIGNAL( iconChanged(QString) ),
+ this, SLOT( slotIconChanged() ) );
+ connect( m_view->commandButton, SIGNAL( clicked() ),
+ this, SLOT( slotCommand() ) );
+}
+
+bool operator==( KDEDesktopMimeType::Service s1, KDEDesktopMimeType::Service s2 )
+{
+ return ( s1.m_strName==s2.m_strName )
+ && ( s1.m_strIcon==s2.m_strIcon )
+ && ( s1.m_strExec==s2.m_strExec );
+}
+
+bool operator!=( KDEDesktopMimeType::Service s1, KDEDesktopMimeType::Service s2 )
+{
+ return !( s1==s2 );
+}
+
+void ServiceConfigDialog::slotOk()
+{
+ KDEDesktopMimeType::Service service;
+ service.m_strName = m_view->labelEdit->text();
+ service.m_strIcon = m_view->iconButton->icon();
+ service.m_strExec = m_view->commandEdit->text();
+
+ QStringList mimetypes;
+
+ uint list_count = m_view->mimetypesSelector->selectedListBox()->count();
+ for( uint i=0; i < list_count; ++i )
+ {
+ QListBoxItem *item = m_view->mimetypesSelector->selectedListBox()->item(i);
+ MimetypeListBoxItem *mime_item = static_cast<MimetypeListBoxItem*>( item );
+ mimetypes.append( mime_item->mimetype() );
+ }
+
+ if ( service!=m_action->service() || mimetypes!=m_action->mimetypes() )
+ {
+ m_action->setService( service );
+ m_action->setMimetypes( mimetypes );
+ accept();
+ }
+ else
+ {
+ reject();
+ }
+}
+
+void ServiceConfigDialog::slotIconChanged()
+{
+ m_iconChanged = true;
+}
+
+void ServiceConfigDialog::slotCommand()
+{
+ KOpenWithDlg d(this);
+ int value = d.exec();
+ if ( value == QDialog::Accepted )
+ {
+ KService::Ptr service = d.service();
+ if ( service != 0L )
+ {
+ m_view->commandEdit->setText( service->exec() );
+ if ( m_iconChanged == false )
+ {
+ m_view->iconButton->setIcon( service->icon() );
+ }
+ }
+ }
+}
+
+#include "serviceconfigdialog.moc"
diff --git a/kioslave/media/kcmodule/serviceconfigdialog.h b/kioslave/media/kcmodule/serviceconfigdialog.h
new file mode 100644
index 000000000..090a978d4
--- /dev/null
+++ b/kioslave/media/kcmodule/serviceconfigdialog.h
@@ -0,0 +1,48 @@
+/* This file is part of the KDE Project
+ Copyright (c) 2005 Jean-Remy Falleri <jr.falleri@laposte.net>
+ Copyright (c) 2005 Kvin Ottens <ervin ipsquad net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef _SERVICECONFIGDIALOG_H_
+#define _SERVICECONFIGDIALOG_H_
+
+#include <kdialogbase.h>
+
+#include "notifierserviceaction.h"
+#include "serviceview.h"
+
+class ServiceConfigDialog : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+ ServiceConfigDialog(NotifierServiceAction *action,
+ const QStringList &mimetypesList,
+ QWidget* parent = 0, const char* name = 0);
+
+public slots:
+ void slotOk();
+ void slotIconChanged();
+ void slotCommand();
+
+private:
+ ServiceView *m_view;
+ NotifierServiceAction *m_action;
+ bool m_iconChanged;
+};
+
+#endif
diff --git a/kioslave/media/kcmodule/serviceview.ui b/kioslave/media/kcmodule/serviceview.ui
new file mode 100644
index 000000000..938a9bf89
--- /dev/null
+++ b/kioslave/media/kcmodule/serviceview.ui
@@ -0,0 +1,248 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>ServiceView</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>ServiceView</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>664</width>
+ <height>503</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>3</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>640</width>
+ <height>480</height>
+ </size>
+ </property>
+ <property name="caption">
+ <string>Edit Service</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QGroupBox" row="0" column="0">
+ <property name="name">
+ <cstring>groupBox1</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Edit Service</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>layout8</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout6</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KIconButton">
+ <property name="name">
+ <cstring>iconButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>40</width>
+ <height>40</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>40</width>
+ <height>40</height>
+ </size>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="iconSize">
+ <number>32</number>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout5</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>spacer4</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Minimum</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>labelEdit</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer5</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Minimum</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>21</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="Line">
+ <property name="name">
+ <cstring>line1</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>HLine</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ </widget>
+ <widget class="KActionSelector">
+ <property name="name">
+ <cstring>mimetypesSelector</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="availableLabel">
+ <string>Available &amp;medium types:</string>
+ </property>
+ <property name="selectedLabel">
+ <string>Displa&amp;y service for:</string>
+ </property>
+ <property name="showUpDownButtons">
+ <bool>false</bool>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout7</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KActiveLabel">
+ <property name="name">
+ <cstring>m_lbCommmand</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Command:</string>
+ </property>
+ </widget>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>commandEdit</cstring>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>commandButton</cstring>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+ </widget>
+ </grid>
+ </widget>
+ </grid>
+</widget>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>kicondialog.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kactionselector.h</includehint>
+ <includehint>kactivelabel.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+</includehints>
+</UI>
diff --git a/kioslave/media/kfile-plugin/Makefile.am b/kioslave/media/kfile-plugin/Makefile.am
new file mode 100644
index 000000000..7f694e28b
--- /dev/null
+++ b/kioslave/media/kfile-plugin/Makefile.am
@@ -0,0 +1,13 @@
+kde_module_LTLIBRARIES = kfile_media.la
+
+kfile_media_la_SOURCES = kfilemediaplugin.cpp
+kfile_media_la_LDFLAGS = $(all_libraries) $(KDE_RPATH) -module $(KDE_PLUGIN)
+kfile_media_la_LIBADD = $(LIB_KIO) ../libmediacommon/libmediacommon.la
+
+kdelnkdir = $(kde_servicesdir)
+kde_services_DATA = kfile_media.desktop
+
+INCLUDES = -I$(srcdir)/../libmediacommon $(all_includes)
+
+METASOURCES = AUTO
+noinst_HEADERS = kfilemediaplugin.h
diff --git a/kioslave/media/kfile-plugin/kfile_media.desktop b/kioslave/media/kfile-plugin/kfile_media.desktop
new file mode 100644
index 000000000..474ab12b2
--- /dev/null
+++ b/kioslave/media/kfile-plugin/kfile_media.desktop
@@ -0,0 +1,75 @@
+[Desktop Entry]
+Type=Service
+Name=Medium Information
+Name[af]=Medium Informasie
+Name[ar]=معلومات عن الوسيط
+Name[az]=Mediyum Mə'lumatı
+Name[be]=Інфармацыя аб носьбітах
+Name[bg]=Информация за устройствата
+Name[bn]=মিডিয়া তথ্য
+Name[bs]=Informacije o mediju
+Name[ca]=Informació de suports
+Name[cs]=Informace o médiu
+Name[csb]=Wëdowiédzô ò zôpisownëch mediach
+Name[da]=Medieinformation
+Name[de]=Medium-Information
+Name[el]=Πληροφορίες μέσου
+Name[eo]=datumportilaj informoj
+Name[es]=Información de recursos
+Name[et]=Andmekandja info
+Name[eu]=Media informazioa
+Name[fa]=اطلاعات رسانه
+Name[fi]=Tallenteiden tiedot
+Name[fr]=Informations sur le média
+Name[fy]=Mediumynformaasje
+Name[ga]=Eolas faoin Mheán
+Name[gl]=Información do Meio
+Name[he]=מידע אודות המדיה
+Name[hi]=माध्यम जानकारी
+Name[hr]=Podaci o mediju
+Name[hu]=Adathordozó-jellemzők
+Name[is]=Upplýsingar um miðil
+Name[it]=Informazioni supporto
+Name[ja]=メディア情報
+Name[ka]=ცნობები მატარებლის შესახებ
+Name[kk]=Тасушының мәліметі
+Name[km]=ព័ត៌មាន​ឧបករណ៍
+Name[ko]=메모리 정보
+Name[lt]=Laikmenos informacija
+Name[lv]=Datu nesēju informācija
+Name[mk]=Информации за носач
+Name[ms]=Maklumat Medium
+Name[mt]=Informazzjoni tal-apparat
+Name[nb]=Medieinformasjon
+Name[nds]=Medium-Informatschoon
+Name[ne]=माध्यम सूचना
+Name[nl]=Mediuminformatie
+Name[nn]=Medieinformasjon
+Name[pa]=ਮਾਧਿਅਮ ਜਾਣਕਾਰੀ
+Name[pl]=Informacje o nośnikach danych
+Name[pt]=Informação do Dispositivo
+Name[pt_BR]=Informações sobre a Mídia
+Name[ro]=Informații mediu
+Name[ru]=Сведения о диске
+Name[rw]=Amakuru y'igitangazamakuru
+Name[se]=Mediumdieđut
+Name[sk]=Informácie o médiu
+Name[sl]=Informacije o mediju
+Name[sr]=Информације о медијуму
+Name[sr@Latn]=Informacije o medijumu
+Name[sv]=Mediainformation
+Name[ta]=சாதனத் தகவல்
+Name[te]=మాధ్యమ సమాచారం
+Name[th]=ข้อมูลของสื่อ
+Name[tr]=Ortam Bilgisi
+Name[tt]=Media Turında
+Name[uk]=Інформація про носій
+Name[uz]=Saqlash uskuna haqida maʼlumot
+Name[uz@cyrillic]=Сақлаш ускуна ҳақида маълумот
+Name[vi]=Thông tin về Ổ lưu trữ
+Name[wa]=Informåcions sol mediom
+Name[zh_CN]=介质信息
+Name[zh_TW]=媒體資訊
+ServiceTypes=KFilePlugin
+X-KDE-Library=kfile_media
+MimeType=media/audiocd;media/hdd_mounted;media/blankcd;media/hdd_unmounted;media/blankdvd;media/cdrom_mounted;media/cdrom_unmounted;media/cdwriter_mounted;media/nfs_mounted;media/cdwriter_unmounted;media/nfs_unmounted;media/removable_mounted;media/dvd_mounted;media/removable_unmounted;media/dvd_unmounted;media/smb_mounted;media/dvdvideo;media/smb_unmounted;media/floppy5_mounted;media/svcd;media/floppy5_unmounted;media/vcd;media/floppy_mounted;media/zip_mounted;media/floppy_unmounted;media/zip_unmounted;media/gphoto2camera;media/camera_mounted;media/camera_unmounted
diff --git a/kioslave/media/kfile-plugin/kfilemediaplugin.cpp b/kioslave/media/kfile-plugin/kfilemediaplugin.cpp
new file mode 100644
index 000000000..c91dbf21a
--- /dev/null
+++ b/kioslave/media/kfile-plugin/kfilemediaplugin.cpp
@@ -0,0 +1,197 @@
+/* This file is part of the KDE project
+ Copyright (C) 2004 Kevin Ottens <ervin ipsquad net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "config.h"
+#include "kfilemediaplugin.h"
+
+#include <kgenericfactory.h>
+
+#include <dcopref.h>
+
+#include <qpixmap.h>
+#include <qpainter.h>
+#include <qstyle.h>
+#include <qapplication.h>
+#include <qfile.h>
+
+#ifdef HAVE_STATVFS
+# include <sys/statvfs.h>
+#else
+# include <sys/mount.h>
+# define statvfs statfs
+# define f_frsize f_bsize
+#endif
+
+typedef KGenericFactory<KFileMediaPlugin> KFileMediaPluginFactory;
+K_EXPORT_COMPONENT_FACTORY(kfile_media, KFileMediaPluginFactory("kio_media"))
+
+KFileMediaPlugin::KFileMediaPlugin(QObject *parent, const char *name,
+ const QStringList& args)
+ : KFilePlugin(parent, name, args)
+{
+ addMimeType( "media/audiocd" );
+ addMimeType( "media/hdd_mounted" );
+ addMimeType( "media/blankcd" );
+ addMimeType( "media/hdd_unmounted" );
+ addMimeType( "media/blankdvd" );
+ addMimeType( "media/cdrom_mounted" );
+ addMimeType( "media/cdrom_unmounted" );
+ addMimeType( "media/cdwriter_mounted" );
+ addMimeType( "media/nfs_mounted" );
+ addMimeType( "media/cdwriter_unmounted" );
+ addMimeType( "media/nfs_unmounted" );
+ addMimeType( "media/removable_mounted" );
+ addMimeType( "media/dvd_mounted" );
+ addMimeType( "media/removable_unmounted" );
+ addMimeType( "media/dvd_unmounted" );
+ addMimeType( "media/smb_mounted" );
+ addMimeType( "media/dvdvideo" );
+ addMimeType( "media/smb_unmounted" );
+ addMimeType( "media/floppy5_mounted" );
+ addMimeType( "media/svcd" );
+ addMimeType( "media/floppy5_unmounted" );
+ addMimeType( "media/vcd" );
+ addMimeType( "media/floppy_mounted" );
+ addMimeType( "media/zip_mounted" );
+ addMimeType( "media/floppy_unmounted" );
+ addMimeType( "media/zip_unmounted" );
+ addMimeType( "media/gphoto2camera" );
+ addMimeType( "media/camera_mounted" );
+ addMimeType( "media/camera_unmounted" );
+}
+
+bool KFileMediaPlugin::readInfo(KFileMetaInfo &info, uint /*what*/)
+{
+ const Medium medium = askMedium(info);
+
+ kdDebug() << "KFileMediaPlugin::readInfo " << medium.id() << endl;
+
+ if (medium.id().isNull()) return false;
+
+ QString mount_point = medium.mountPoint();
+ KURL base_url = medium.prettyBaseURL();
+ QString device_node = medium.deviceNode();
+
+ KFileMetaInfoGroup group = appendGroup(info, "mediumInfo");
+
+ if (base_url.isValid())
+ {
+ appendItem(group, "baseURL", base_url.prettyURL());
+ }
+
+ if (!device_node.isEmpty())
+ {
+ appendItem(group, "deviceNode", device_node);
+ }
+
+ if (!mount_point.isEmpty() && medium.isMounted())
+ {
+ m_total = 0;
+ m_used = 0;
+ m_free = 0;
+
+ struct statvfs vfs;
+ memset(&vfs, 0, sizeof(vfs));
+
+ if ( ::statvfs(QFile::encodeName(mount_point), &vfs) != -1 )
+ {
+ m_total = static_cast<KIO::filesize_t>(vfs.f_blocks) * static_cast<KIO::filesize_t>(vfs.f_frsize);
+ m_free = static_cast<KIO::filesize_t>(vfs.f_bavail) * static_cast<KIO::filesize_t>(vfs.f_frsize);
+ m_used = m_total - m_free;
+
+ int percent = 0;
+ int length = 0;
+
+ if (m_total != 0)
+ {
+ percent = 100 * m_used / m_total;
+ length = 150 * m_used / m_total;
+ }
+
+ appendItem(group, "free", m_free);
+ appendItem(group, "used", m_used);
+ appendItem(group, "total", m_total);
+
+ group = appendGroup(info, "mediumSummary");
+
+ appendItem(group, "percent", QString("%1%").arg(percent));
+
+ QPixmap bar(150, 20);
+ QPainter p(&bar);
+
+ p.fillRect(0, 0, length, 20, Qt::red);
+ p.fillRect(length, 0, 150-length, 20, Qt::green);
+
+ QColorGroup cg = QApplication::palette().active();
+
+ QApplication::style().drawPrimitive(QStyle::PE_Panel, &p,
+ QRect(0, 0, 150, 20), cg,
+ QStyle::Style_Sunken);
+
+ appendItem( group, "thumbnail", bar );
+ }
+ }
+
+ return true;
+}
+
+const Medium KFileMediaPlugin::askMedium(KFileMetaInfo &info)
+{
+ DCOPRef mediamanager("kded", "mediamanager");
+ kdDebug() << "properties " << info.url() << endl;
+ DCOPReply reply = mediamanager.call( "properties", info.url().url() );
+
+ if ( !reply.isValid() )
+ {
+ return Medium(QString::null, QString::null);
+ }
+
+ return Medium::create(reply);
+}
+
+void KFileMediaPlugin::addMimeType(const char *mimeType)
+{
+ KFileMimeTypeInfo *info = addMimeTypeInfo( mimeType );
+
+ KFileMimeTypeInfo::GroupInfo *group
+ = addGroupInfo(info, "mediumInfo", i18n("Medium Information"));
+
+ KFileMimeTypeInfo::ItemInfo *item
+ = addItemInfo(group, "free", i18n("Free"), QVariant::ULongLong);
+ setUnit(item, KFileMimeTypeInfo::Bytes);
+
+ item = addItemInfo(group, "used", i18n("Used"), QVariant::ULongLong);
+ setUnit(item, KFileMimeTypeInfo::Bytes);
+
+ item = addItemInfo(group, "total", i18n("Total"), QVariant::ULongLong);
+ setUnit(item, KFileMimeTypeInfo::Bytes);
+
+ item = addItemInfo(group, "baseURL", i18n("Base URL"), QVariant::String);
+ item = addItemInfo(group, "mountPoint", i18n("Mount Point"), QVariant::String);
+ item = addItemInfo(group, "deviceNode", i18n("Device Node"), QVariant::String);
+
+ group = addGroupInfo(info, "mediumSummary", i18n("Medium Summary"));
+
+ item = addItemInfo(group, "percent", i18n("Usage"), QVariant::String);
+
+ item = addItemInfo( group, "thumbnail", i18n("Bar Graph"), QVariant::Image );
+ setHint( item, KFileMimeTypeInfo::Thumbnail );
+}
+
+#include "kfilemediaplugin.moc"
diff --git a/kioslave/media/kfile-plugin/kfilemediaplugin.h b/kioslave/media/kfile-plugin/kfilemediaplugin.h
new file mode 100644
index 000000000..666f75df3
--- /dev/null
+++ b/kioslave/media/kfile-plugin/kfilemediaplugin.h
@@ -0,0 +1,47 @@
+/* This file is part of the KDE project
+ Copyright (C) 2004 Kevin Ottens <ervin ipsquad net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef _KFILE_MEDIA_H_
+#define _KFILE_MEDIA_H_
+
+#include <kfilemetainfo.h>
+#include <kurl.h>
+#include <kio/global.h>
+
+#include "medium.h"
+
+class KFileMediaPlugin : public KFilePlugin
+{
+Q_OBJECT
+public:
+ KFileMediaPlugin(QObject *parent, const char *name,
+ const QStringList &args);
+
+ bool readInfo(KFileMetaInfo &info, uint what = KFileMetaInfo::Fastest);
+
+private:
+ void addMimeType(const char *mimeType);
+ const Medium askMedium(KFileMetaInfo &info);
+
+ KIO::filesize_t m_total;
+ KIO::filesize_t m_used;
+ KIO::filesize_t m_free;
+};
+
+#endif
diff --git a/kioslave/media/kio_media.cpp b/kioslave/media/kio_media.cpp
new file mode 100644
index 000000000..b9283592c
--- /dev/null
+++ b/kioslave/media/kio_media.cpp
@@ -0,0 +1,275 @@
+/* This file is part of the KDE project
+ Copyright (c) 2004 Kevin Ottens <ervin ipsquad net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <stdlib.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+#include <kapplication.h>
+#include <dcopclient.h>
+#include <kcmdlineargs.h>
+
+#include <qeventloop.h>
+
+#include "kio_media.h"
+
+
+static const KCmdLineOptions options[] =
+{
+ { "+protocol", I18N_NOOP( "Protocol name" ), 0 },
+ { "+pool", I18N_NOOP( "Socket name" ), 0 },
+ { "+app", I18N_NOOP( "Socket name" ), 0 },
+ KCmdLineLastOption
+};
+
+extern "C" {
+ int KDE_EXPORT kdemain( int argc, char **argv )
+ {
+ // KApplication is necessary to use other ioslaves
+ putenv(strdup("SESSION_MANAGER="));
+ KCmdLineArgs::init(argc, argv, "kio_media", 0, 0, 0, 0);
+ KCmdLineArgs::addCmdLineOptions( options );
+ KApplication app( false, false );
+ // We want to be anonymous even if we use DCOP
+ app.dcopClient()->attach();
+
+ KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
+ MediaProtocol slave( args->arg(0), args->arg(1), args->arg(2) );
+ slave.dispatchLoop();
+ return 0;
+ }
+}
+
+
+MediaProtocol::MediaProtocol(const QCString &protocol,
+ const QCString &pool, const QCString &app)
+ : ForwardingSlaveBase(protocol, pool, app)
+{
+ connect( &m_impl, SIGNAL( warning( const QString & ) ),
+ this, SLOT( slotWarning( const QString & ) ) );
+}
+
+MediaProtocol::~MediaProtocol()
+{
+}
+
+bool MediaProtocol::rewriteURL(const KURL &url, KURL &newUrl)
+{
+ QString name, path;
+
+ if ( !m_impl.parseURL(url, name, path) )
+ {
+ error(KIO::ERR_MALFORMED_URL, url.prettyURL());
+ return false;
+ }
+
+
+ if ( !m_impl.realURL(name, path, newUrl) )
+ {
+ error( m_impl.lastErrorCode(), m_impl.lastErrorMessage() );
+ return false;
+ }
+
+ return true;
+}
+
+void MediaProtocol::put(const KURL &url, int permissions,
+ bool overwrite, bool resume)
+{
+ kdDebug(1219) << "MediaProtocol::put: " << url << endl;
+
+ QString name, path;
+ bool ok = m_impl.parseURL(url, name, path);
+
+ if ( ok && path.isEmpty() )
+ {
+ error(KIO::ERR_CANNOT_OPEN_FOR_WRITING, url.prettyURL());
+ }
+ else
+ {
+ ForwardingSlaveBase::put(url, permissions, overwrite, resume);
+ }
+}
+
+void MediaProtocol::rename(const KURL &src, const KURL &dest, bool overwrite)
+{
+ kdDebug(1219) << "MediaProtocol::rename: " << src << ", " << dest << ", "
+ << overwrite << endl;
+
+ QString src_name, src_path;
+ bool ok = m_impl.parseURL(src, src_name, src_path);
+ QString dest_name, dest_path;
+ ok &= m_impl.parseURL(dest, dest_name, dest_path);
+
+ if ( ok && src_path.isEmpty() && dest_path.isEmpty()
+ && src.protocol() == "media" && dest.protocol() == "media" )
+ {
+ if (!m_impl.setUserLabel(src_name, dest_name))
+ {
+ error(m_impl.lastErrorCode(), m_impl.lastErrorMessage());
+ }
+ else
+ {
+ finished();
+ }
+ }
+ else
+ {
+ ForwardingSlaveBase::rename(src, dest, overwrite);
+ }
+}
+
+void MediaProtocol::mkdir(const KURL &url, int permissions)
+{
+ kdDebug(1219) << "MediaProtocol::mkdir: " << url << endl;
+
+ QString name, path;
+ bool ok = m_impl.parseURL(url, name, path);
+
+ if ( ok && path.isEmpty() )
+ {
+ error(KIO::ERR_COULD_NOT_MKDIR, url.prettyURL());
+ }
+ else
+ {
+ ForwardingSlaveBase::mkdir(url, permissions);
+ }
+}
+
+void MediaProtocol::del(const KURL &url, bool isFile)
+{
+ kdDebug(1219) << "MediaProtocol::del: " << url << endl;
+
+ QString name, path;
+ bool ok = m_impl.parseURL(url, name, path);
+
+ if ( ok && path.isEmpty() )
+ {
+ error(KIO::ERR_CANNOT_DELETE, url.prettyURL());
+ }
+ else
+ {
+ ForwardingSlaveBase::del(url, isFile);
+ }
+}
+
+void MediaProtocol::stat(const KURL &url)
+{
+ kdDebug(1219) << "MediaProtocol::stat: " << url << endl;
+ QString path = url.path();
+ if( path.isEmpty() || path == "/" )
+ {
+ // The root is "virtual" - it's not a single physical directory
+ KIO::UDSEntry entry;
+ m_impl.createTopLevelEntry( entry );
+ statEntry( entry );
+ finished();
+ return;
+ }
+
+ QString name;
+ bool ok = m_impl.parseURL(url, name, path);
+
+ if ( !ok )
+ {
+ error(KIO::ERR_MALFORMED_URL, url.prettyURL());
+ return;
+ }
+
+ if( path.isEmpty() )
+ {
+ KIO::UDSEntry entry;
+
+ if ( m_impl.statMedium(name, entry)
+ || m_impl.statMediumByLabel(name, entry) )
+ {
+ statEntry(entry);
+ finished();
+ }
+ else
+ {
+ error(KIO::ERR_DOES_NOT_EXIST, url.prettyURL());
+ }
+ }
+ else
+ {
+ ForwardingSlaveBase::stat(url);
+ }
+}
+
+void MediaProtocol::listDir(const KURL &url)
+{
+ kdDebug(1219) << "MediaProtocol::listDir: " << url << endl;
+
+ if ( url.path().length() <= 1 )
+ {
+ listRoot();
+ return;
+ }
+
+ QString name, path;
+ bool ok = m_impl.parseURL(url, name, path);
+
+ if ( !ok )
+ {
+ error(KIO::ERR_MALFORMED_URL, url.prettyURL());
+ return;
+ }
+
+ ForwardingSlaveBase::listDir(url);
+}
+
+void MediaProtocol::listRoot()
+{
+ KIO::UDSEntry entry;
+
+ KIO::UDSEntryList media_entries;
+ bool ok = m_impl.listMedia(media_entries);
+
+ if (!ok)
+ {
+ error( m_impl.lastErrorCode(), m_impl.lastErrorMessage() );
+ return;
+ }
+
+ totalSize(media_entries.count()+1);
+
+ m_impl.createTopLevelEntry(entry);
+ listEntry(entry, false);
+
+ KIO::UDSEntryListIterator it = media_entries.begin();
+ KIO::UDSEntryListIterator end = media_entries.end();
+
+ for(; it!=end; ++it)
+ {
+ listEntry(*it, false);
+ }
+
+ entry.clear();
+ listEntry(entry, true);
+
+ finished();
+}
+
+void MediaProtocol::slotWarning( const QString &msg )
+{
+ warning( msg );
+}
+
+#include "kio_media.moc"
diff --git a/kioslave/media/kio_media.h b/kioslave/media/kio_media.h
new file mode 100644
index 000000000..55b3ae670
--- /dev/null
+++ b/kioslave/media/kio_media.h
@@ -0,0 +1,54 @@
+/* This file is part of the KDE project
+ Copyright (c) 2004 Kevin Ottens <ervin ipsquad net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef _KIO_MEDIA_H_
+#define _KIO_MEDIA_H_
+
+#include <kio/forwardingslavebase.h>
+
+#include "mediaimpl.h"
+
+class MediaProtocol : public KIO::ForwardingSlaveBase
+{
+Q_OBJECT
+public:
+ MediaProtocol(const QCString &protocol, const QCString &pool,
+ const QCString &app);
+ virtual ~MediaProtocol();
+
+ virtual bool rewriteURL(const KURL &url, KURL &newUrl);
+
+ virtual void put(const KURL &url, int permissions,
+ bool overwrite, bool resume);
+ virtual void rename(const KURL &src, const KURL &dest, bool overwrite);
+ virtual void mkdir(const KURL &url, int permissions);
+ virtual void del(const KURL &url, bool isFile);
+ virtual void stat(const KURL &url);
+ virtual void listDir(const KURL &url);
+
+private slots:
+ void slotWarning( const QString &msg );
+
+private:
+ void listRoot();
+
+ MediaImpl m_impl;
+};
+
+#endif
diff --git a/kioslave/media/libmediacommon/Makefile.am b/kioslave/media/libmediacommon/Makefile.am
new file mode 100644
index 000000000..dd27d265a
--- /dev/null
+++ b/kioslave/media/libmediacommon/Makefile.am
@@ -0,0 +1,11 @@
+INCLUDES = $(all_includes)
+METASOURCES = AUTO
+
+noinst_LTLIBRARIES = libmediacommon.la
+libmediacommon_la_SOURCES = medium.cpp actionlistboxitem.cpp \
+ notifieraction.cpp notifierserviceaction.cpp \
+ notifiernothingaction.cpp notifieropenaction.cpp \
+ notifiersettings.cpp mediamanagersettings.kcfgc
+
+kde_kcfg_DATA = mediamanagersettings.kcfg
+
diff --git a/kioslave/media/libmediacommon/actionlistboxitem.cpp b/kioslave/media/libmediacommon/actionlistboxitem.cpp
new file mode 100644
index 000000000..3551857c1
--- /dev/null
+++ b/kioslave/media/libmediacommon/actionlistboxitem.cpp
@@ -0,0 +1,47 @@
+/* This file is part of the KDE Project
+ Copyright (c) 2005 Jean-Remy Falleri <jr.falleri@laposte.net>
+ Copyright (c) 2005 Kévin Ottens <ervin ipsquad net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "actionlistboxitem.h"
+
+#include <klocale.h>
+
+#include <qpixmap.h>
+
+ActionListBoxItem::ActionListBoxItem(NotifierAction *action, QString mimetype, QListBox *parent)
+ : QListBoxPixmap(parent, action->pixmap()),
+ m_action(action)
+{
+ QString text = m_action->label();
+
+ if ( m_action->autoMimetypes().contains( mimetype ) )
+ {
+ text += " (" + i18n( "Auto Action" ) + ")";
+ }
+
+ setText( text );
+}
+
+ActionListBoxItem::~ActionListBoxItem()
+{
+}
+
+NotifierAction *ActionListBoxItem::action() const
+{
+ return m_action;
+}
diff --git a/kioslave/media/libmediacommon/actionlistboxitem.h b/kioslave/media/libmediacommon/actionlistboxitem.h
new file mode 100644
index 000000000..cdd8a3ff1
--- /dev/null
+++ b/kioslave/media/libmediacommon/actionlistboxitem.h
@@ -0,0 +1,40 @@
+/* This file is part of the KDE Project
+ Copyright (c) 2005 Jean-Remy Falleri <jr.falleri@laposte.net>
+ Copyright (c) 2005 Kvin Ottens <ervin ipsquad net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef _ACTIONLISTBOXITEM_H_
+#define _ACTIONLISTBOXITEM_H_
+
+#include <qlistbox.h>
+#include <qstring.h>
+
+#include "notifieraction.h"
+
+class ActionListBoxItem : public QListBoxPixmap
+{
+public:
+ ActionListBoxItem(NotifierAction *action, QString mimetype, QListBox *parent);
+ ~ActionListBoxItem();
+
+ NotifierAction *action() const;
+
+private:
+ NotifierAction *m_action;
+};
+
+#endif
diff --git a/kioslave/media/libmediacommon/mediamanagersettings.kcfg b/kioslave/media/libmediacommon/mediamanagersettings.kcfg
new file mode 100644
index 000000000..4c9615ade
--- /dev/null
+++ b/kioslave/media/libmediacommon/mediamanagersettings.kcfg
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE kcfg SYSTEM "http://www.kde.org/standards/kcfg/1.0/kcfg.dtd">
+
+<kcfg>
+ <kcfgfile name="mediamanagerrc"/>
+ <group name="Global">
+ <entry name="HalBackendEnabled" type="Bool">
+ <label>Enable HAL backend</label>
+ <whatsthis>When HAL (Hardware Abstraction Layer) support is enabled, KDE will use it to gather information on the storage media available in your system.</whatsthis>
+ <default>true</default>
+ </entry>
+ <entry name="CdPollingEnabled" type="Bool">
+ <label>Enable CD polling</label>
+ <whatsthis>Allows KDE to poll CD-Rom or DVD-Rom drives itself in order to detect medium insert.</whatsthis>
+ <default>true</default>
+ </entry>
+ <entry name="AutostartEnabled" type="Bool">
+ <label>Enable medium application autostart after mount</label>
+ <whatsthis>Allows KDE to autostart application after a medium mount if it contains an Autostart or an Autoopen file.</whatsthis>
+ <default>true</default>
+ </entry>
+ </group>
+</kcfg>
diff --git a/kioslave/media/libmediacommon/mediamanagersettings.kcfgc b/kioslave/media/libmediacommon/mediamanagersettings.kcfgc
new file mode 100644
index 000000000..bbc58d92e
--- /dev/null
+++ b/kioslave/media/libmediacommon/mediamanagersettings.kcfgc
@@ -0,0 +1,4 @@
+File=mediamanagersettings.kcfg
+ClassName=MediaManagerSettings
+Singleton=true
+Mutators=true
diff --git a/kioslave/media/libmediacommon/medium.cpp b/kioslave/media/libmediacommon/medium.cpp
new file mode 100644
index 000000000..5767a6c9a
--- /dev/null
+++ b/kioslave/media/libmediacommon/medium.cpp
@@ -0,0 +1,228 @@
+/* This file is part of the KDE Project
+ Copyright (c) 2004 Kévin Ottens <ervin ipsquad net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "medium.h"
+
+#include <kconfig.h>
+#include <klocale.h>
+
+const QString Medium::SEPARATOR = "---";
+
+Medium::Medium(const QString &id, const QString &name)
+{
+ m_properties+= id; /* ID */
+ m_properties+= name; /* NAME */
+ m_properties+= name; /* LABEL */
+ m_properties+= QString::null; /* USER_LABEL */
+
+ m_properties+= "false"; /* MOUNTABLE */
+ m_properties+= QString::null; /* DEVICE_NODE */
+ m_properties+= QString::null; /* MOUNT_POINT */
+ m_properties+= QString::null; /* FS_TYPE */
+ m_properties+= "false"; /* MOUNTED */
+ m_properties+= QString::null; /* BASE_URL */
+ m_properties+= QString::null; /* MIME_TYPE */
+ m_properties+= QString::null; /* ICON_NAME */
+
+ loadUserLabel();
+
+ m_halmounted = false;
+}
+
+Medium::Medium()
+{
+ m_properties+= QString::null; /* ID */
+ m_properties+= QString::null; /* NAME */
+ m_properties+= QString::null; /* LABEL */
+ m_properties+= QString::null; /* USER_LABEL */
+
+ m_properties+= QString::null; /* MOUNTABLE */
+ m_properties+= QString::null; /* DEVICE_NODE */
+ m_properties+= QString::null; /* MOUNT_POINT */
+ m_properties+= QString::null; /* FS_TYPE */
+ m_properties+= QString::null; /* MOUNTED */
+ m_properties+= QString::null; /* BASE_URL */
+ m_properties+= QString::null; /* MIME_TYPE */
+ m_properties+= QString::null; /* ICON_NAME */
+
+ m_halmounted = false;
+}
+
+const Medium Medium::create(const QStringList &properties)
+{
+ Medium m;
+
+ if ( properties.size() >= PROPERTIES_COUNT )
+ {
+ m.m_properties[ID] = properties[ID];
+ m.m_properties[NAME] = properties[NAME];
+ m.m_properties[LABEL] = properties[LABEL];
+ m.m_properties[USER_LABEL] = properties[USER_LABEL];
+
+ m.m_properties[MOUNTABLE] = properties[MOUNTABLE];
+ m.m_properties[DEVICE_NODE] = properties[DEVICE_NODE];
+ m.m_properties[MOUNT_POINT] = properties[MOUNT_POINT];
+ m.m_properties[FS_TYPE] = properties[FS_TYPE];
+ m.m_properties[MOUNTED] = properties[MOUNTED];
+ m.m_properties[BASE_URL] = properties[BASE_URL];
+ m.m_properties[MIME_TYPE] = properties[MIME_TYPE];
+ m.m_properties[ICON_NAME] = properties[ICON_NAME];
+ }
+
+ return m;
+}
+
+Medium::List Medium::createList(const QStringList &properties)
+{
+ List l;
+
+ if ( properties.size() % (PROPERTIES_COUNT+1) == 0)
+ {
+ int media_count = properties.size()/(PROPERTIES_COUNT+1);
+
+ QStringList props = properties;
+
+ for(int i=0; i<media_count; i++)
+ {
+ const Medium m = create(props);
+ l.append(m);
+
+ QStringList::iterator first = props.begin();
+ QStringList::iterator last = props.find(SEPARATOR);
+ ++last;
+ props.erase(first, last);
+ }
+ }
+
+ return l;
+}
+
+
+void Medium::setName(const QString &name)
+{
+ m_properties[NAME] = name;
+}
+
+void Medium::setLabel(const QString &label)
+{
+ m_properties[LABEL] = label;
+}
+
+void Medium::setUserLabel(const QString &label)
+{
+ KConfig cfg("mediamanagerrc");
+ cfg.setGroup("UserLabels");
+
+ QString entry_name = m_properties[ID];
+
+ if ( label.isNull() )
+ {
+ cfg.deleteEntry(entry_name);
+ }
+ else
+ {
+ cfg.writeEntry(entry_name, label);
+ }
+
+ m_properties[USER_LABEL] = label;
+}
+
+void Medium::loadUserLabel()
+{
+ KConfig cfg("mediamanagerrc");
+ cfg.setGroup("UserLabels");
+
+ QString entry_name = m_properties[ID];
+
+ if ( cfg.hasKey(entry_name) )
+ {
+ m_properties[USER_LABEL] = cfg.readEntry(entry_name);
+ }
+ else
+ {
+ m_properties[USER_LABEL] = QString::null;
+ }
+}
+
+
+bool Medium::mountableState(bool mounted)
+{
+ if ( m_properties[DEVICE_NODE].isEmpty()
+ || ( mounted && m_properties[MOUNT_POINT].isEmpty() ) )
+ {
+ return false;
+ }
+
+ m_properties[MOUNTABLE] = "true";
+ m_properties[MOUNTED] = ( mounted ? "true" : "false" );
+
+ return true;
+}
+
+void Medium::mountableState(const QString &deviceNode,
+ const QString &mountPoint,
+ const QString &fsType, bool mounted)
+{
+ m_properties[MOUNTABLE] = "true";
+ m_properties[DEVICE_NODE] = deviceNode;
+ m_properties[MOUNT_POINT] = mountPoint;
+ m_properties[FS_TYPE] = fsType;
+ m_properties[MOUNTED] = ( mounted ? "true" : "false" );
+}
+
+void Medium::unmountableState(const QString &baseURL)
+{
+ m_properties[MOUNTABLE] = "false";
+ m_properties[BASE_URL] = baseURL;
+}
+
+void Medium::setMimeType(const QString &mimeType)
+{
+ m_properties[MIME_TYPE] = mimeType;
+}
+
+void Medium::setIconName(const QString &iconName)
+{
+ m_properties[ICON_NAME] = iconName;
+}
+
+bool Medium::needMounting() const
+{
+ return isMountable() && !isMounted();
+}
+
+KURL Medium::prettyBaseURL() const
+{
+ if ( !baseURL().isEmpty() )
+ return baseURL();
+
+ return KURL( mountPoint() );
+}
+
+QString Medium::prettyLabel() const
+{
+ if ( !userLabel().isEmpty() )
+ {
+ return userLabel();
+ }
+ else
+ {
+ return label();
+ }
+}
+
diff --git a/kioslave/media/libmediacommon/medium.h b/kioslave/media/libmediacommon/medium.h
new file mode 100644
index 000000000..f94545e8e
--- /dev/null
+++ b/kioslave/media/libmediacommon/medium.h
@@ -0,0 +1,110 @@
+/* This file is part of the KDE Project
+ Copyright (c) 2004 Kvin Ottens <ervin ipsquad net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef _MEDIUM_H_
+#define _MEDIUM_H_
+
+#include <qstring.h>
+#include <qstringlist.h>
+#include <kurl.h>
+#include <qmap.h>
+
+class Medium
+{
+public:
+ typedef QValueList<const Medium> List;
+
+ static const uint ID = 0;
+ static const uint NAME = 1;
+ static const uint LABEL = 2;
+ static const uint USER_LABEL = 3;
+ static const uint MOUNTABLE = 4;
+ static const uint DEVICE_NODE = 5;
+ static const uint MOUNT_POINT = 6;
+ static const uint FS_TYPE = 7;
+ static const uint MOUNTED = 8;
+ static const uint BASE_URL = 9;
+ static const uint MIME_TYPE = 10;
+ static const uint ICON_NAME = 11;
+ static const uint PROPERTIES_COUNT = 12;
+ static const QString SEPARATOR;
+
+ Medium(const QString &id, const QString &name);
+ static const Medium create(const QStringList &properties);
+ static List createList(const QStringList &properties);
+
+ const QStringList &properties() const { return m_properties; }
+
+ QString id() const { return m_properties[ID]; }
+ QString name() const { return m_properties[NAME]; }
+ QString label() const { return m_properties[LABEL]; }
+ QString userLabel() const { return m_properties[USER_LABEL]; }
+ bool isMountable() const { return m_properties[MOUNTABLE]=="true"; }
+ QString deviceNode() const { return m_properties[DEVICE_NODE]; }
+ QString mountPoint() const { return m_properties[MOUNT_POINT]; }
+ QString fsType() const { return m_properties[FS_TYPE]; }
+ bool isMounted() const { return m_properties[MOUNTED]=="true"; }
+ QString baseURL() const { return m_properties[BASE_URL]; }
+ QString mimeType() const { return m_properties[MIME_TYPE]; }
+ QString iconName() const { return m_properties[ICON_NAME]; }
+
+ bool needMounting() const;
+ KURL prettyBaseURL() const;
+ QString prettyLabel() const;
+
+ void setName(const QString &name);
+ void setLabel(const QString &label);
+ void setUserLabel(const QString &label);
+
+ bool mountableState(bool mounted);
+ void mountableState(const QString &deviceNode,
+ const QString &mountPoint,
+ const QString &fsType, bool mounted);
+ void unmountableState(const QString &baseURL = QString::null);
+
+ void setMimeType(const QString &mimeType);
+ void setIconName(const QString &iconName);
+ void setHalMounted(bool flag) const { m_halmounted = flag; }
+ bool halMounted() const { return m_halmounted; }
+
+private:
+ Medium();
+ void loadUserLabel();
+
+ QStringList m_properties;
+ mutable bool m_halmounted;
+
+friend class QValueListNode<const Medium>;
+};
+
+namespace MediaManagerUtils {
+ static inline QMap<QString,QString> splitOptions(const QStringList & options)
+ {
+ QMap<QString,QString> valids;
+
+ for (QStringList::ConstIterator it = options.begin(); it != options.end(); ++it)
+ {
+ QString key = (*it).left((*it).find('='));
+ QString value = (*it).mid((*it).find('=') + 1);
+ valids[key] = value;
+ }
+ return valids;
+ }
+}
+
+#endif
diff --git a/kioslave/media/libmediacommon/notifieraction.cpp b/kioslave/media/libmediacommon/notifieraction.cpp
new file mode 100644
index 000000000..3eea682d4
--- /dev/null
+++ b/kioslave/media/libmediacommon/notifieraction.cpp
@@ -0,0 +1,97 @@
+/* This file is part of the KDE Project
+ Copyright (c) 2005 Jean-Remy Falleri <jr.falleri@laposte.net>
+ Copyright (c) 2005 Kévin Ottens <ervin ipsquad net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "notifieraction.h"
+
+#include <qfile.h>
+#include <kglobal.h>
+#include <kiconloader.h>
+#include <kicontheme.h>
+
+NotifierAction::NotifierAction()
+{
+}
+
+NotifierAction::~NotifierAction()
+{
+}
+
+void NotifierAction::setIconName(const QString &iconName)
+{
+ m_iconName = iconName;
+}
+
+void NotifierAction::setLabel(const QString &label)
+{
+ m_label = label;
+}
+
+QString NotifierAction::iconName() const
+{
+ return m_iconName;
+}
+
+QPixmap NotifierAction::pixmap() const
+{
+ QFile f( m_iconName );
+
+ if ( f.exists() )
+ {
+ return QPixmap( m_iconName );
+ }
+ else
+ {
+ QString path = KGlobal::iconLoader()->iconPath( m_iconName, -32 );
+ return QPixmap( path );
+ }
+}
+
+QString NotifierAction::label() const
+{
+ return m_label;
+}
+
+void NotifierAction::addAutoMimetype( const QString &mimetype )
+{
+ if ( !m_autoMimetypes.contains( mimetype ) )
+ {
+ m_autoMimetypes.append( mimetype );
+ }
+}
+
+void NotifierAction::removeAutoMimetype( const QString &mimetype )
+{
+ m_autoMimetypes.remove( mimetype );
+}
+
+QStringList NotifierAction::autoMimetypes()
+{
+ return m_autoMimetypes;
+}
+
+bool NotifierAction::isWritable() const
+{
+ return false;
+}
+
+bool NotifierAction::supportsMimetype(const QString &/*mimetype*/) const
+{
+ return true;
+}
+
diff --git a/kioslave/media/libmediacommon/notifieraction.h b/kioslave/media/libmediacommon/notifieraction.h
new file mode 100644
index 000000000..028ce7433
--- /dev/null
+++ b/kioslave/media/libmediacommon/notifieraction.h
@@ -0,0 +1,60 @@
+/* This file is part of the KDE Project
+ Copyright (c) 2005 Jean-Remy Falleri <jr.falleri@laposte.net>
+ Copyright (c) 2005 Kvin Ottens <ervin ipsquad net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef _NOTIFIERACTION_H_
+#define _NOTIFIERACTION_H_
+
+#include <kfileitem.h>
+#include <qstring.h>
+#include <qpixmap.h>
+
+class NotifierSettings;
+
+class NotifierAction
+{
+public:
+ NotifierAction();
+ virtual ~NotifierAction();
+
+ virtual QString label() const;
+ virtual QString iconName() const;
+ virtual void setLabel( const QString &label );
+ virtual void setIconName( const QString &icon );
+
+ QPixmap pixmap() const;
+
+ QStringList autoMimetypes();
+
+ virtual QString id() const = 0;
+ virtual bool isWritable() const;
+ virtual bool supportsMimetype( const QString &mimetype ) const;
+ virtual void execute( KFileItem &medium ) = 0;
+
+private:
+ void addAutoMimetype( const QString &mimetype );
+ void removeAutoMimetype( const QString &mimetype );
+
+ QString m_label;
+ QString m_iconName;
+ QStringList m_autoMimetypes;
+
+ friend class NotifierSettings;
+};
+
+#endif
diff --git a/kioslave/media/libmediacommon/notifiernothingaction.cpp b/kioslave/media/libmediacommon/notifiernothingaction.cpp
new file mode 100644
index 000000000..adf7fcf04
--- /dev/null
+++ b/kioslave/media/libmediacommon/notifiernothingaction.cpp
@@ -0,0 +1,39 @@
+/* This file is part of the KDE Project
+ Copyright (c) 2005 Jean-Remy Falleri <jr.falleri@laposte.net>
+ Copyright (c) 2005 Kévin Ottens <ervin ipsquad net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "notifiernothingaction.h"
+
+#include <klocale.h>
+
+NotifierNothingAction::NotifierNothingAction()
+ : NotifierAction()
+{
+ setIconName("button_cancel");
+ setLabel(i18n("Do Nothing"));
+}
+
+QString NotifierNothingAction::id() const
+{
+ return "#NothinAction";
+}
+
+void NotifierNothingAction::execute(KFileItem &/*medium*/)
+{
+}
+
diff --git a/kioslave/media/libmediacommon/notifiernothingaction.h b/kioslave/media/libmediacommon/notifiernothingaction.h
new file mode 100644
index 000000000..6fd564f61
--- /dev/null
+++ b/kioslave/media/libmediacommon/notifiernothingaction.h
@@ -0,0 +1,34 @@
+/* This file is part of the KDE Project
+ Copyright (c) 2005 Jean-Remy Falleri <jr.falleri@laposte.net>
+ Copyright (c) 2005 Kvin Ottens <ervin ipsquad net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef _NOTIFIERNOTHINGACTION_H_
+#define _NOTIFIERNOTHINGACTION_H_
+
+#include "notifieraction.h"
+
+class NotifierNothingAction : public NotifierAction
+{
+public:
+ NotifierNothingAction();
+ virtual QString id() const;
+ virtual void execute(KFileItem &medium);
+};
+
+#endif
+
diff --git a/kioslave/media/libmediacommon/notifieropenaction.cpp b/kioslave/media/libmediacommon/notifieropenaction.cpp
new file mode 100644
index 000000000..82db14b97
--- /dev/null
+++ b/kioslave/media/libmediacommon/notifieropenaction.cpp
@@ -0,0 +1,45 @@
+/* This file is part of the KDE Project
+ Copyright (c) 2005 Jean-Remy Falleri <jr.falleri@laposte.net>
+ Copyright (c) 2005 Kévin Ottens <ervin ipsquad net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "notifieropenaction.h"
+
+#include <klocale.h>
+
+NotifierOpenAction::NotifierOpenAction()
+ : NotifierAction()
+{
+ setIconName("window_new");
+ setLabel(i18n("Open in New Window"));
+}
+
+QString NotifierOpenAction::id() const
+{
+ return "#OpenAction";
+}
+
+void NotifierOpenAction::execute(KFileItem &medium)
+{
+ medium.run();
+}
+
+bool NotifierOpenAction::supportsMimetype( const QString &mimetype ) const
+{
+ return !mimetype.contains( "blank" );
+}
+
diff --git a/kioslave/media/libmediacommon/notifieropenaction.h b/kioslave/media/libmediacommon/notifieropenaction.h
new file mode 100644
index 000000000..3239e5ca2
--- /dev/null
+++ b/kioslave/media/libmediacommon/notifieropenaction.h
@@ -0,0 +1,34 @@
+/* This file is part of the KDE Project
+ Copyright (c) 2005 Jean-Remy Falleri <jr.falleri@laposte.net>
+ Copyright (c) 2005 Kvin Ottens <ervin ipsquad net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef _NOTIFIEROPENACTION_H_
+#define _NOTIFIEROPENACTION_H_
+
+#include "notifieraction.h"
+
+class NotifierOpenAction : public NotifierAction
+{
+public:
+ NotifierOpenAction();
+ virtual QString id() const;
+ virtual void execute(KFileItem &medium);
+ bool supportsMimetype( const QString &mimetype ) const;
+};
+
+#endif
diff --git a/kioslave/media/libmediacommon/notifierserviceaction.cpp b/kioslave/media/libmediacommon/notifierserviceaction.cpp
new file mode 100644
index 000000000..ee2401945
--- /dev/null
+++ b/kioslave/media/libmediacommon/notifierserviceaction.cpp
@@ -0,0 +1,166 @@
+/* This file is part of the KDE Project
+ Copyright (c) 2005 Jean-Remy Falleri <jr.falleri@laposte.net>
+ Copyright (c) 2005 Kévin Ottens <ervin ipsquad net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "notifierserviceaction.h"
+
+#include <qdir.h>
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <kstddirs.h>
+#include <kdesktopfile.h>
+#include <klocale.h>
+
+NotifierServiceAction::NotifierServiceAction()
+ : NotifierAction()
+{
+ NotifierAction::setIconName("button_cancel");
+ NotifierAction::setLabel(i18n("Unknown"));
+
+ m_service.m_strName = "New Service";
+ m_service.m_strIcon = "button_cancel";
+ m_service.m_strExec = "konqueror %u";
+}
+
+QString NotifierServiceAction::id() const
+{
+ if (m_filePath.isEmpty() || m_service.m_strName.isEmpty())
+ {
+ return QString();
+ }
+ else
+ {
+ return "#Service:"+m_filePath;
+ }
+}
+
+void NotifierServiceAction::setIconName( const QString &icon )
+{
+ m_service.m_strIcon = icon;
+ NotifierAction::setIconName( icon );
+}
+
+void NotifierServiceAction::setLabel( const QString &label )
+{
+ m_service.m_strName = label;
+ NotifierAction::setLabel( label );
+
+ updateFilePath();
+}
+
+void NotifierServiceAction::execute(KFileItem &medium)
+{
+ KURL::List urls = KURL::List( medium.url() );
+ KDEDesktopMimeType::executeService( urls, m_service );
+}
+
+void NotifierServiceAction::setService(KDEDesktopMimeType::Service service)
+{
+ NotifierAction::setIconName( service.m_strIcon );
+ NotifierAction::setLabel( service.m_strName );
+
+ m_service = service;
+
+ updateFilePath();
+}
+
+KDEDesktopMimeType::Service NotifierServiceAction::service() const
+{
+ return m_service;
+}
+
+void NotifierServiceAction::setFilePath(const QString &filePath)
+{
+ m_filePath = filePath;
+}
+
+QString NotifierServiceAction::filePath() const
+{
+ return m_filePath;
+}
+
+void NotifierServiceAction::updateFilePath()
+{
+ if ( !m_filePath.isEmpty() ) return;
+
+ QString action_name = m_service.m_strName;
+ action_name.replace( " ", "_" );
+
+ QDir actions_dir( locateLocal( "data", "konqueror/servicemenus/", true ) );
+
+ QString filename = actions_dir.absFilePath( action_name + ".desktop" );
+
+ int counter = 1;
+ while ( QFile::exists( filename ) )
+ {
+ filename = actions_dir.absFilePath( action_name
+ + QString::number( counter )
+ + ".desktop" );
+ counter++;
+ }
+
+ m_filePath = filename;
+}
+
+void NotifierServiceAction::setMimetypes(const QStringList &mimetypes)
+{
+ m_mimetypes = mimetypes;
+}
+
+QStringList NotifierServiceAction::mimetypes()
+{
+ return m_mimetypes;
+}
+
+bool NotifierServiceAction::isWritable() const
+{
+ QFileInfo info( m_filePath );
+
+ if ( info.exists() )
+ {
+ return info.isWritable();
+ }
+ else
+ {
+ info = QFileInfo( info.dirPath() );
+ return info.isWritable();
+ }
+}
+
+bool NotifierServiceAction::supportsMimetype(const QString &mimetype) const
+{
+ return m_mimetypes.contains(mimetype);
+}
+
+void NotifierServiceAction::save() const
+{
+ QFile::remove( m_filePath );
+ KDesktopFile desktopFile(m_filePath);
+
+ desktopFile.setGroup(QString("Desktop Action ") + m_service.m_strName);
+ desktopFile.writeEntry(QString("Icon"), m_service.m_strIcon);
+ desktopFile.writeEntry(QString("Name"), m_service.m_strName);
+ desktopFile.writeEntry(QString("Exec"), m_service.m_strExec);
+
+ desktopFile.setDesktopGroup();
+
+ desktopFile.writeEntry(QString("ServiceTypes"), m_mimetypes, ",");
+ desktopFile.writeEntry(QString("Actions"),
+ QStringList(m_service.m_strName),";");
+}
+
diff --git a/kioslave/media/libmediacommon/notifierserviceaction.h b/kioslave/media/libmediacommon/notifierserviceaction.h
new file mode 100644
index 000000000..4d61a6b74
--- /dev/null
+++ b/kioslave/media/libmediacommon/notifierserviceaction.h
@@ -0,0 +1,61 @@
+/* This file is part of the KDE Project
+ Copyright (c) 2005 Jean-Remy Falleri <jr.falleri@laposte.net>
+ Copyright (c) 2005 Kvin Ottens <ervin ipsquad net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef _NOTIFIERSERVICEACTION_H_
+#define _NOTIFIERSERVICEACTION_H_
+
+#include <kmimetype.h>
+#include <qstring.h>
+
+#include "notifieraction.h"
+
+class NotifierServiceAction : public NotifierAction
+{
+public:
+ NotifierServiceAction();
+ virtual QString id() const;
+ virtual void execute(KFileItem &item);
+
+ virtual void setIconName( const QString &icon );
+ virtual void setLabel( const QString &label );
+
+ void setService(KDEDesktopMimeType::Service service);
+ KDEDesktopMimeType::Service service() const;
+
+ void setFilePath(const QString &filePath);
+ QString filePath() const;
+
+ void setMimetypes(const QStringList &mimetypes);
+ QStringList mimetypes();
+
+ virtual bool isWritable() const;
+ virtual bool supportsMimetype(const QString &mimetype) const;
+
+ void save() const;
+
+private:
+ void updateFilePath();
+
+ KDEDesktopMimeType::Service m_service;
+ QString m_filePath;
+ QStringList m_mimetypes;
+};
+
+#endif
+
diff --git a/kioslave/media/libmediacommon/notifiersettings.cpp b/kioslave/media/libmediacommon/notifiersettings.cpp
new file mode 100644
index 000000000..c7ad616a5
--- /dev/null
+++ b/kioslave/media/libmediacommon/notifiersettings.cpp
@@ -0,0 +1,379 @@
+/* This file is part of the KDE Project
+ Copyright (c) 2005 Jean-Remy Falleri <jr.falleri@laposte.net>
+ Copyright (c) 2005 Kévin Ottens <ervin ipsquad net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "notifiersettings.h"
+
+#include <kglobal.h>
+#include <kdesktopfile.h>
+#include <kstandarddirs.h>
+#include <qdir.h>
+#include <qfile.h>
+
+#include "notifieropenaction.h"
+#include "notifiernothingaction.h"
+
+
+NotifierSettings::NotifierSettings()
+{
+ m_supportedMimetypes.append( "media/removable_unmounted" );
+ m_supportedMimetypes.append( "media/removable_mounted" );
+ m_supportedMimetypes.append( "media/camera_unmounted" );
+ m_supportedMimetypes.append( "media/camera_mounted" );
+ m_supportedMimetypes.append( "media/gphoto2camera" );
+ m_supportedMimetypes.append( "media/cdrom_unmounted" );
+ m_supportedMimetypes.append( "media/cdrom_mounted" );
+ m_supportedMimetypes.append( "media/dvd_unmounted" );
+ m_supportedMimetypes.append( "media/dvd_mounted" );
+ m_supportedMimetypes.append( "media/cdwriter_unmounted" );
+ m_supportedMimetypes.append( "media/cdwriter_mounted" );
+ m_supportedMimetypes.append( "media/blankcd" );
+ m_supportedMimetypes.append( "media/blankdvd" );
+ m_supportedMimetypes.append( "media/audiocd" );
+ m_supportedMimetypes.append( "media/dvdvideo" );
+ m_supportedMimetypes.append( "media/vcd" );
+ m_supportedMimetypes.append( "media/svcd" );
+
+ reload();
+}
+
+NotifierSettings::~NotifierSettings()
+{
+ while ( !m_actions.isEmpty() )
+ {
+ NotifierAction *a = m_actions.first();
+ m_actions.remove( a );
+ delete a;
+ }
+
+ while ( !m_deletedActions.isEmpty() )
+ {
+ NotifierServiceAction *a = m_deletedActions.first();
+ m_deletedActions.remove( a );
+ delete a;
+ }
+}
+
+QValueList<NotifierAction*> NotifierSettings::actions()
+{
+ return m_actions;
+}
+
+const QStringList &NotifierSettings::supportedMimetypes()
+{
+ return m_supportedMimetypes;
+}
+
+QValueList<NotifierAction*> NotifierSettings::actionsForMimetype( const QString &mimetype )
+{
+ QValueList<NotifierAction*> result;
+
+ QValueList<NotifierAction*>::iterator it = m_actions.begin();
+ QValueList<NotifierAction*>::iterator end = m_actions.end();
+
+ for ( ; it!=end; ++it )
+ {
+ if ( (*it)->supportsMimetype( mimetype ) )
+ {
+ result.append( *it );
+ }
+ }
+
+ return result;
+}
+
+bool NotifierSettings::addAction( NotifierServiceAction *action )
+{
+ if ( !m_idMap.contains( action->id() ) )
+ {
+ m_actions.insert( --m_actions.end(), action );
+ m_idMap[ action->id() ] = action;
+ return true;
+ }
+ return false;
+}
+
+bool NotifierSettings::deleteAction( NotifierServiceAction *action )
+{
+ if ( action->isWritable() )
+ {
+ m_actions.remove( action );
+ m_idMap.remove( action->id() );
+ m_deletedActions.append( action );
+
+ QStringList auto_mimetypes = action->autoMimetypes();
+ QStringList::iterator it = auto_mimetypes.begin();
+ QStringList::iterator end = auto_mimetypes.end();
+
+ for ( ; it!=end; ++it )
+ {
+ action->removeAutoMimetype( *it );
+ m_autoMimetypesMap.remove( *it );
+ }
+
+ return true;
+ }
+ return false;
+}
+
+void NotifierSettings::setAutoAction( const QString &mimetype, NotifierAction *action )
+{
+ resetAutoAction( mimetype );
+ m_autoMimetypesMap[mimetype] = action;
+ action->addAutoMimetype( mimetype );
+}
+
+
+void NotifierSettings::resetAutoAction( const QString &mimetype )
+{
+ if ( m_autoMimetypesMap.contains( mimetype ) )
+ {
+ NotifierAction *action = m_autoMimetypesMap[mimetype];
+ action->removeAutoMimetype( mimetype );
+ m_autoMimetypesMap.remove(mimetype);
+ }
+}
+
+void NotifierSettings::clearAutoActions()
+{
+ QMap<QString,NotifierAction*>::iterator it = m_autoMimetypesMap.begin();
+ QMap<QString,NotifierAction*>::iterator end = m_autoMimetypesMap.end();
+
+ for ( ; it!=end; ++it )
+ {
+ NotifierAction *action = it.data();
+ QString mimetype = it.key();
+
+ if ( action )
+ action->removeAutoMimetype( mimetype );
+ m_autoMimetypesMap[mimetype] = 0L;
+ }
+}
+
+NotifierAction *NotifierSettings::autoActionForMimetype( const QString &mimetype )
+{
+ if ( m_autoMimetypesMap.contains( mimetype ) )
+ {
+ return m_autoMimetypesMap[mimetype];
+ }
+ else
+ {
+ return 0L;
+ }
+}
+
+void NotifierSettings::reload()
+{
+ while ( !m_actions.isEmpty() )
+ {
+ NotifierAction *a = m_actions.first();
+ m_actions.remove( a );
+ delete a;
+ }
+
+ while ( !m_deletedActions.isEmpty() )
+ {
+ NotifierServiceAction *a = m_deletedActions.first();
+ m_deletedActions.remove( a );
+ delete a;
+ }
+
+ m_idMap.clear();
+ m_autoMimetypesMap.clear();
+
+ NotifierOpenAction *open = new NotifierOpenAction();
+ m_actions.append( open );
+ m_idMap[ open->id() ] = open;
+
+ QValueList<NotifierServiceAction*> services = listServices();
+
+ QValueList<NotifierServiceAction*>::iterator serv_it = services.begin();
+ QValueList<NotifierServiceAction*>::iterator serv_end = services.end();
+
+ for ( ; serv_it!=serv_end; ++serv_it )
+ {
+ m_actions.append( *serv_it );
+ m_idMap[ (*serv_it)->id() ] = *serv_it;
+ }
+
+ NotifierNothingAction *nothing = new NotifierNothingAction();
+ m_actions.append( nothing );
+ m_idMap[ nothing->id() ] = nothing;
+
+ KConfig config( "medianotifierrc", true );
+ QMap<QString,QString> auto_actions_map = config.entryMap( "Auto Actions" );
+
+ QMap<QString,QString>::iterator auto_it = auto_actions_map.begin();
+ QMap<QString,QString>::iterator auto_end = auto_actions_map.end();
+
+ for ( ; auto_it!=auto_end; ++auto_it )
+ {
+ QString mime = auto_it.key();
+ QString action_id = auto_it.data();
+
+ if ( m_idMap.contains( action_id ) )
+ {
+ setAutoAction( mime, m_idMap[action_id] );
+ }
+ else
+ {
+ config.deleteEntry( mime );
+ }
+ }
+}
+void NotifierSettings::save()
+{
+ QValueList<NotifierAction*>::iterator act_it = m_actions.begin();
+ QValueList<NotifierAction*>::iterator act_end = m_actions.end();
+
+ for ( ; act_it!=act_end; ++act_it )
+ {
+ NotifierServiceAction *service;
+ if ( ( service=dynamic_cast<NotifierServiceAction*>( *act_it ) )
+ && service->isWritable() )
+ {
+ service->save();
+ }
+ }
+
+ while ( !m_deletedActions.isEmpty() )
+ {
+ NotifierServiceAction *a = m_deletedActions.first();
+ m_deletedActions.remove( a );
+ QFile::remove( a->filePath() );
+ delete a;
+ }
+
+ KSimpleConfig config( "medianotifierrc" );
+ config.setGroup( "Auto Actions" );
+
+ QMap<QString,NotifierAction*>::iterator auto_it = m_autoMimetypesMap.begin();
+ QMap<QString,NotifierAction*>::iterator auto_end = m_autoMimetypesMap.end();
+
+ for ( ; auto_it!=auto_end; ++auto_it )
+ {
+ if ( auto_it.data()!=0L )
+ {
+ config.writeEntry( auto_it.key(), auto_it.data()->id() );
+ }
+ else
+ {
+ config.deleteEntry( auto_it.key() );
+ }
+ }
+}
+
+QValueList<NotifierServiceAction*> NotifierSettings::loadActions( KDesktopFile &desktop ) const
+{
+ desktop.setDesktopGroup();
+
+ QValueList<NotifierServiceAction*> services;
+
+ const QString filename = desktop.fileName();
+ const QStringList mimetypes = desktop.readListEntry( "ServiceTypes" );
+
+ QValueList<KDEDesktopMimeType::Service> type_services
+ = KDEDesktopMimeType::userDefinedServices(filename, true);
+
+ QValueList<KDEDesktopMimeType::Service>::iterator service_it = type_services.begin();
+ QValueList<KDEDesktopMimeType::Service>::iterator service_end = type_services.end();
+ for (; service_it!=service_end; ++service_it)
+ {
+ NotifierServiceAction *service_action
+ = new NotifierServiceAction();
+
+ service_action->setService( *service_it );
+ service_action->setFilePath( filename );
+ service_action->setMimetypes( mimetypes );
+
+ services += service_action;
+ }
+
+ return services;
+}
+
+
+bool NotifierSettings::shouldLoadActions( KDesktopFile &desktop, const QString &mimetype ) const
+{
+ desktop.setDesktopGroup();
+
+ if ( desktop.hasKey( "Actions" )
+ && desktop.hasKey( "ServiceTypes" )
+ && !desktop.readBoolEntry( "X-KDE-MediaNotifierHide", false ) )
+ {
+ const QStringList actions = desktop.readListEntry( "Actions" );
+
+ if ( actions.size()!=1 )
+ {
+ return false;
+ }
+
+ const QStringList types = desktop.readListEntry( "ServiceTypes" );
+
+ if ( mimetype.isEmpty() )
+ {
+ QStringList::ConstIterator type_it = types.begin();
+ QStringList::ConstIterator type_end = types.end();
+ for (; type_it != type_end; ++type_it)
+ {
+ if ( (*type_it).startsWith( "media/" ) )
+ {
+ return true;
+ }
+ }
+ }
+ else if ( types.contains(mimetype) )
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+QValueList<NotifierServiceAction*> NotifierSettings::listServices( const QString &mimetype ) const
+{
+ QValueList<NotifierServiceAction*> services;
+ QStringList dirs = KGlobal::dirs()->findDirs("data", "konqueror/servicemenus/");
+
+ QStringList::ConstIterator dir_it = dirs.begin();
+ QStringList::ConstIterator dir_end = dirs.end();
+ for (; dir_it != dir_end; ++dir_it)
+ {
+ QDir dir( *dir_it );
+
+ QStringList entries = dir.entryList( "*.desktop", QDir::Files );
+
+ QStringList::ConstIterator entry_it = entries.begin();
+ QStringList::ConstIterator entry_end = entries.end();
+
+ for (; entry_it != entry_end; ++entry_it )
+ {
+ QString filename = *dir_it + *entry_it;
+
+ KDesktopFile desktop( filename, true );
+
+ if ( shouldLoadActions(desktop, mimetype) )
+ {
+ services+=loadActions(desktop);
+ }
+ }
+ }
+
+ return services;
+}
diff --git a/kioslave/media/libmediacommon/notifiersettings.h b/kioslave/media/libmediacommon/notifiersettings.h
new file mode 100644
index 000000000..6ddee318b
--- /dev/null
+++ b/kioslave/media/libmediacommon/notifiersettings.h
@@ -0,0 +1,63 @@
+/* This file is part of the KDE Project
+ Copyright (c) 2005 Jean-Remy Falleri <jr.falleri@laposte.net>
+ Copyright (c) 2005 Kvin Ottens <ervin ipsquad net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef _NOTIFIERSETTINGS_H_
+#define _NOTIFIERSETTINGS_H_
+
+#include <qvaluelist.h>
+#include <qmap.h>
+
+#include "notifieraction.h"
+#include "notifierserviceaction.h"
+
+
+class NotifierSettings
+{
+public:
+ NotifierSettings();
+ ~NotifierSettings();
+
+ QValueList<NotifierAction*> actions();
+ QValueList<NotifierAction*> actionsForMimetype( const QString &mimetype );
+
+ bool addAction( NotifierServiceAction *action );
+ bool deleteAction( NotifierServiceAction *action );
+
+ void setAutoAction( const QString &mimetype, NotifierAction *action );
+ void resetAutoAction( const QString &mimetype );
+ void clearAutoActions();
+ NotifierAction *autoActionForMimetype( const QString &mimetype );
+
+ const QStringList &supportedMimetypes();
+
+ void reload();
+ void save();
+
+private:
+ QValueList<NotifierServiceAction*> listServices( const QString &mimetype = QString() ) const;
+ bool shouldLoadActions( KDesktopFile &desktop, const QString &mimetype ) const;
+ QValueList<NotifierServiceAction*> loadActions( KDesktopFile &desktop ) const;
+
+ QStringList m_supportedMimetypes;
+ QValueList<NotifierAction*> m_actions;
+ QValueList<NotifierServiceAction*> m_deletedActions;
+ QMap<QString,NotifierAction*> m_idMap;
+ QMap<QString,NotifierAction*> m_autoMimetypesMap;
+};
+#endif
diff --git a/kioslave/media/media.protocol b/kioslave/media/media.protocol
new file mode 100644
index 000000000..053611c1f
--- /dev/null
+++ b/kioslave/media/media.protocol
@@ -0,0 +1,18 @@
+[Protocol]
+exec=kio_media
+protocol=media
+input=none
+output=filesystem
+listing=Name,Type,Size,Date,AccessDate,Access,Owner,Group,Link
+reading=true
+writing=true
+makedir=true
+deleting=true
+linking=true
+moving=true
+Icon=system
+maxInstances=4
+#TODO DocPath=kioslave/file.html
+Class=:local
+deleteRecursive=true
+fileNameUsedForCopying=Name
diff --git a/kioslave/media/mediaimpl.cpp b/kioslave/media/mediaimpl.cpp
new file mode 100644
index 000000000..741227cdb
--- /dev/null
+++ b/kioslave/media/mediaimpl.cpp
@@ -0,0 +1,429 @@
+/* This file is part of the KDE project
+ Copyright (c) 2004 Kevin Ottens <ervin ipsquad net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "mediaimpl.h"
+
+#include <klocale.h>
+#include <kdebug.h>
+#include <dcopclient.h>
+#include <dcopref.h>
+#include <kio/netaccess.h>
+
+#include <kmimetype.h>
+
+#include <kapplication.h>
+#include <qeventloop.h>
+
+#include <sys/stat.h>
+
+#include "medium.h"
+
+MediaImpl::MediaImpl() : QObject(), DCOPObject("mediaimpl"), mp_mounting(0L)
+{
+
+}
+
+bool MediaImpl::parseURL(const KURL &url, QString &name, QString &path) const
+{
+ QString url_path = url.path();
+
+ int i = url_path.find('/', 1);
+ if (i > 0)
+ {
+ name = url_path.mid(1, i-1);
+ path = url_path.mid(i+1);
+ }
+ else
+ {
+ name = url_path.mid(1);
+ path = QString::null;
+ }
+
+ return name != QString::null;
+}
+
+bool MediaImpl::realURL(const QString &name, const QString &path, KURL &url)
+{
+ bool ok;
+ Medium m = findMediumByName(name, ok);
+ if ( !ok ) return false;
+
+ ok = ensureMediumMounted(m);
+ if ( !ok ) return false;
+
+ url = m.prettyBaseURL();
+ url.addPath(path);
+ return true;
+}
+
+
+bool MediaImpl::statMedium(const QString &name, KIO::UDSEntry &entry)
+{
+ kdDebug(1219) << "MediaImpl::statMedium: " << name << endl;
+
+ DCOPRef mediamanager("kded", "mediamanager");
+ DCOPReply reply = mediamanager.call( "properties", name );
+
+ if ( !reply.isValid() )
+ {
+ m_lastErrorCode = KIO::ERR_SLAVE_DEFINED;
+ m_lastErrorMessage = i18n("The KDE mediamanager is not running.");
+ return false;
+ }
+
+ Medium m = Medium::create(reply);
+
+ if (m.id().isEmpty())
+ {
+ entry.clear();
+ return false;
+ }
+
+ createMediumEntry(entry, m);
+
+ return true;
+}
+
+bool MediaImpl::statMediumByLabel(const QString &label, KIO::UDSEntry &entry)
+{
+ kdDebug(1219) << "MediaImpl::statMediumByLabel: " << label << endl;
+
+ DCOPRef mediamanager("kded", "mediamanager");
+ DCOPReply reply = mediamanager.call( "nameForLabel", label );
+
+ if ( !reply.isValid() )
+ {
+ m_lastErrorCode = KIO::ERR_SLAVE_DEFINED;
+ m_lastErrorMessage = i18n("The KDE mediamanager is not running.");
+ return false;
+ }
+
+ QString name = reply;
+
+ if (name.isEmpty())
+ {
+ entry.clear();
+ return false;
+ }
+
+ return statMedium(name, entry);
+}
+
+
+bool MediaImpl::listMedia(QValueList<KIO::UDSEntry> &list)
+{
+ kdDebug(1219) << "MediaImpl::listMedia" << endl;
+
+ DCOPRef mediamanager("kded", "mediamanager");
+ DCOPReply reply = mediamanager.call( "fullList" );
+
+ if ( !reply.isValid() )
+ {
+ m_lastErrorCode = KIO::ERR_SLAVE_DEFINED;
+ m_lastErrorMessage = i18n("The KDE mediamanager is not running.");
+ return false;
+ }
+
+ Medium::List media = Medium::createList(reply);
+
+ KIO::UDSEntry entry;
+
+ Medium::List::iterator it = media.begin();
+ Medium::List::iterator end = media.end();
+
+ for(; it!=end; ++it)
+ {
+ entry.clear();
+
+ createMediumEntry(entry, *it);
+
+ list.append(entry);
+ }
+
+ return true;
+}
+
+bool MediaImpl::setUserLabel(const QString &name, const QString &label)
+{
+ kdDebug(1219) << "MediaImpl::setUserLabel: " << name << ", " << label << endl;
+
+
+ DCOPRef mediamanager("kded", "mediamanager");
+ DCOPReply reply = mediamanager.call( "nameForLabel", label );
+
+ if ( !reply.isValid() )
+ {
+ m_lastErrorCode = KIO::ERR_SLAVE_DEFINED;
+ m_lastErrorMessage = i18n("The KDE mediamanager is not running.");
+ return false;
+ }
+ else
+ {
+ QString returned_name = reply;
+ if (!returned_name.isEmpty()
+ && returned_name!=name)
+ {
+ m_lastErrorCode = KIO::ERR_DIR_ALREADY_EXIST;
+ m_lastErrorMessage = i18n("This media name already exists.");
+ return false;
+ }
+ }
+
+ reply = mediamanager.call( "setUserLabel", name, label );
+
+ if ( !reply.isValid() )
+ {
+ m_lastErrorCode = KIO::ERR_SLAVE_DEFINED;
+ m_lastErrorMessage = i18n("The KDE mediamanager is not running.");
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+}
+
+const Medium MediaImpl::findMediumByName(const QString &name, bool &ok)
+{
+ DCOPRef mediamanager("kded", "mediamanager");
+ DCOPReply reply = mediamanager.call( "properties", name );
+
+ if ( reply.isValid() )
+ {
+ ok = true;
+ }
+ else
+ {
+ m_lastErrorCode = KIO::ERR_SLAVE_DEFINED;
+ m_lastErrorMessage = i18n("The KDE mediamanager is not running.");
+ ok = false;
+ }
+
+ return Medium::create(reply);
+}
+
+bool MediaImpl::ensureMediumMounted(Medium &medium)
+{
+ if (medium.id().isEmpty())
+ {
+ m_lastErrorCode = KIO::ERR_COULD_NOT_MOUNT;
+ m_lastErrorMessage = i18n("No such medium.");
+ return false;
+ }
+
+ if ( medium.needMounting() )
+ {
+ m_lastErrorCode = 0;
+
+ mp_mounting = &medium;
+
+
+ /*
+ KIO::Job* job = KIO::mount(false, 0,
+ medium.deviceNode(),
+ medium.mountPoint());
+ job->setAutoWarningHandlingEnabled(false);
+ connect( job, SIGNAL( result( KIO::Job * ) ),
+ this, SLOT( slotMountResult( KIO::Job * ) ) );
+ connect( job, SIGNAL( warning( KIO::Job *, const QString & ) ),
+ this, SLOT( slotWarning( KIO::Job *, const QString & ) ) );
+ */
+ kapp->dcopClient()
+ ->connectDCOPSignal("kded", "mediamanager",
+ "mediumChanged(QString, bool)",
+ "mediaimpl",
+ "slotMediumChanged(QString)",
+ false);
+
+ DCOPRef mediamanager("kded", "mediamanager");
+ DCOPReply reply = mediamanager.call( "mount", medium.id());
+ if (reply.isValid())
+ reply.get(m_lastErrorMessage);
+ else
+ m_lastErrorMessage = i18n("Internal Error");
+ if (!m_lastErrorMessage.isEmpty())
+ m_lastErrorCode = KIO::ERR_SLAVE_DEFINED;
+ else {
+ qApp->eventLoop()->enterLoop();
+ }
+
+ mp_mounting = 0L;
+
+ kapp->dcopClient()
+ ->disconnectDCOPSignal("kded", "mediamanager",
+ "mediumChanged(QString, bool)",
+ "mediaimpl",
+ "slotMediumChanged(QString)");
+
+ return m_lastErrorCode==0;
+ }
+
+ return true;
+}
+
+void MediaImpl::slotWarning( KIO::Job * /*job*/, const QString &msg )
+{
+ emit warning( msg );
+}
+
+void MediaImpl::slotMountResult(KIO::Job *job)
+{
+ kdDebug(1219) << "MediaImpl::slotMountResult" << endl;
+
+ if ( job->error() != 0)
+ {
+ m_lastErrorCode = job->error();
+ m_lastErrorMessage = job->errorText();
+ qApp->eventLoop()->exitLoop();
+ }
+}
+
+void MediaImpl::slotMediumChanged(const QString &name)
+{
+ kdDebug(1219) << "MediaImpl::slotMediumChanged:" << name << endl;
+
+ if (mp_mounting->name()==name)
+ {
+ kdDebug(1219) << "MediaImpl::slotMediumChanged: updating mp_mounting" << endl;
+ bool ok;
+ *mp_mounting = findMediumByName(name, ok);
+ qApp->eventLoop()->exitLoop();
+ }
+}
+
+static void addAtom(KIO::UDSEntry &entry, unsigned int ID, long l,
+ const QString &s = QString::null)
+{
+ KIO::UDSAtom atom;
+ atom.m_uds = ID;
+ atom.m_long = l;
+ atom.m_str = s;
+ entry.append(atom);
+}
+
+
+void MediaImpl::createTopLevelEntry(KIO::UDSEntry& entry) const
+{
+ entry.clear();
+ addAtom(entry, KIO::UDS_URL, 0, "media:/");
+ addAtom(entry, KIO::UDS_NAME, 0, ".");
+ addAtom(entry, KIO::UDS_FILE_TYPE, S_IFDIR);
+ addAtom(entry, KIO::UDS_ACCESS, 0555);
+ addAtom(entry, KIO::UDS_MIME_TYPE, 0, "inode/directory");
+ addAtom(entry, KIO::UDS_ICON_NAME, 0, "blockdevice");
+}
+
+void MediaImpl::slotStatResult(KIO::Job *job)
+{
+ if ( job->error() == 0)
+ {
+ KIO::StatJob *stat_job = static_cast<KIO::StatJob *>(job);
+ m_entryBuffer = stat_job->statResult();
+ }
+
+ qApp->eventLoop()->exitLoop();
+}
+
+KIO::UDSEntry MediaImpl::extractUrlInfos(const KURL &url)
+{
+ m_entryBuffer.clear();
+
+ KIO::StatJob *job = KIO::stat(url, false);
+ job->setAutoWarningHandlingEnabled( false );
+ connect( job, SIGNAL( result(KIO::Job *) ),
+ this, SLOT( slotStatResult(KIO::Job *) ) );
+ connect( job, SIGNAL( warning( KIO::Job *, const QString & ) ),
+ this, SLOT( slotWarning( KIO::Job *, const QString & ) ) );
+ qApp->eventLoop()->enterLoop();
+
+ KIO::UDSEntry::iterator it = m_entryBuffer.begin();
+ KIO::UDSEntry::iterator end = m_entryBuffer.end();
+
+ KIO::UDSEntry infos;
+
+ for(; it!=end; ++it)
+ {
+ switch( (*it).m_uds )
+ {
+ case KIO::UDS_ACCESS:
+ case KIO::UDS_USER:
+ case KIO::UDS_GROUP:
+ case KIO::UDS_CREATION_TIME:
+ case KIO::UDS_MODIFICATION_TIME:
+ case KIO::UDS_ACCESS_TIME:
+ infos.append(*it);
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (url.isLocalFile())
+ {
+ addAtom(infos, KIO::UDS_LOCAL_PATH, 0, url.path());
+ }
+
+ return infos;
+}
+
+
+void MediaImpl::createMediumEntry(KIO::UDSEntry& entry,
+ const Medium &medium)
+{
+ kdDebug(1219) << "MediaProtocol::createMedium" << endl;
+
+ QString url = "media:/"+medium.name();
+
+ kdDebug(1219) << "url = " << url << ", mime = " << medium.mimeType() << endl;
+
+ entry.clear();
+
+ addAtom(entry, KIO::UDS_URL, 0, url);
+
+ QString label = KIO::encodeFileName( medium.prettyLabel() );
+ addAtom(entry, KIO::UDS_NAME, 0, label);
+
+ addAtom(entry, KIO::UDS_FILE_TYPE, S_IFDIR);
+
+ addAtom(entry, KIO::UDS_MIME_TYPE, 0, medium.mimeType());
+ addAtom(entry, KIO::UDS_GUESSED_MIME_TYPE, 0, "inode/directory");
+
+ if (!medium.iconName().isEmpty())
+ {
+ addAtom(entry, KIO::UDS_ICON_NAME, 0, medium.iconName());
+ }
+ else
+ {
+ QString mime = medium.mimeType();
+ QString icon = KMimeType::mimeType(mime)->icon(mime, false);
+ addAtom(entry, KIO::UDS_ICON_NAME, 0, icon);
+ }
+
+ if (medium.needMounting())
+ {
+ addAtom(entry, KIO::UDS_ACCESS, 0400);
+ }
+ else
+ {
+ KURL url = medium.prettyBaseURL();
+ entry+= extractUrlInfos(url);
+ }
+}
+
+#include "mediaimpl.moc"
diff --git a/kioslave/media/mediaimpl.h b/kioslave/media/mediaimpl.h
new file mode 100644
index 000000000..2d82aefda
--- /dev/null
+++ b/kioslave/media/mediaimpl.h
@@ -0,0 +1,81 @@
+/* This file is part of the KDE project
+ Copyright (c) 2004 Kevin Ottens <ervin ipsquad net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef _MEDIAIMPL_H_
+#define _MEDIAIMPL_H_
+
+#include <kio/global.h>
+#include <kio/job.h>
+#include <kurl.h>
+#include <dcopobject.h>
+
+#include <qobject.h>
+#include <qstring.h>
+
+#include "medium.h"
+
+class MediaImpl : public QObject, public DCOPObject
+{
+Q_OBJECT
+K_DCOP
+public:
+ MediaImpl();
+ bool parseURL(const KURL &url, QString &name, QString &path) const;
+ bool realURL(const QString &name, const QString &path, KURL &url);
+
+ bool statMedium(const QString &name, KIO::UDSEntry &entry);
+ bool statMediumByLabel(const QString &label, KIO::UDSEntry &entry);
+ bool listMedia(QValueList<KIO::UDSEntry> &list);
+ bool setUserLabel(const QString &name, const QString &label);
+
+ void createTopLevelEntry(KIO::UDSEntry& entry) const;
+
+ int lastErrorCode() const { return m_lastErrorCode; }
+ QString lastErrorMessage() const { return m_lastErrorMessage; }
+
+k_dcop:
+ void slotMediumChanged(const QString &name);
+
+signals:
+ void warning(const QString &msg);
+
+private slots:
+ void slotWarning(KIO::Job *job, const QString &msg);
+ void slotMountResult(KIO::Job *job);
+ void slotStatResult(KIO::Job *job);
+
+private:
+ const Medium findMediumByName(const QString &name, bool &ok);
+ bool ensureMediumMounted(Medium &medium);
+
+ KIO::UDSEntry extractUrlInfos(const KURL &url);
+ KIO::UDSEntry m_entryBuffer;
+
+ void createMediumEntry(KIO::UDSEntry& entry,
+ const Medium &medium);
+
+ Medium *mp_mounting;
+
+ /// Last error code stored in class to simplify API.
+ /// Note that this means almost no method can be const.
+ int m_lastErrorCode;
+ QString m_lastErrorMessage;
+};
+
+#endif
diff --git a/kioslave/media/mediamanager/Makefile.am b/kioslave/media/mediamanager/Makefile.am
new file mode 100644
index 000000000..45289a9eb
--- /dev/null
+++ b/kioslave/media/mediamanager/Makefile.am
@@ -0,0 +1,32 @@
+kde_module_LTLIBRARIES = kded_mediamanager.la
+
+if include_media_halbackend
+HALBACKEND_INCS = $(HAL_INCS) $(DBUS_INCS) $(DBUSQT_INCS)
+endif
+
+METASOURCES = AUTO
+INCLUDES = -I$(srcdir)/../libmediacommon -I../libmediacommon $(HALBACKEND_INCS) $(all_includes)
+
+if include_media_halbackend
+HALBACKEND_LIB = libhalbackend.la
+libhalbackend_la_SOURCES = halbackend.cpp
+libhalbackend_la_LDFLAGS = -avoid-version $(all_libraries) -no-undefined
+libhalbackend_la_LIBADD = $(HAL_LIBS) $(DBUS_LIBS) $(DBUSQT_LIBS)
+endif
+
+if include_media_linuxcdpolling
+LINUXCDPOLLING_LIB = liblinuxcdpolling.la
+liblinuxcdpolling_la_SOURCES = linuxcdpolling.cpp
+liblinuxcdpolling_la_LDFLAGS = -avoid-version $(all_libraries) -no-undefined
+endif
+
+noinst_LTLIBRARIES = $(LINUXCDPOLLING_LIB) $(HALBACKEND_LIB)
+
+kded_mediamanager_la_SOURCES = mediamanager.cpp mediamanager.skel medialist.cpp backendbase.cpp fstabbackend.cpp removablebackend.cpp mediadirnotify.cpp mediadirnotify.skel
+kded_mediamanager_la_LDFLAGS = $(all_libraries) -module -avoid-version
+kded_mediamanager_la_LIBADD = $(LIB_KSYCOCA) ../libmediacommon/libmediacommon.la $(HALBACKEND_LIB) $(LINUXCDPOLLING_LIB)
+
+
+servicesdir = $(kde_servicesdir)/kded
+services_DATA = mediamanager.desktop
+
diff --git a/kioslave/media/mediamanager/backendbase.cpp b/kioslave/media/mediamanager/backendbase.cpp
new file mode 100644
index 000000000..157acfca5
--- /dev/null
+++ b/kioslave/media/mediamanager/backendbase.cpp
@@ -0,0 +1,26 @@
+/* This file is part of the KDE Project
+ Copyright (c) 2004 Kévin Ottens <ervin ipsquad net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "backendbase.h"
+
+BackendBase::BackendBase(MediaList &list)
+ : m_mediaList(list)
+{
+
+}
+
diff --git a/kioslave/media/mediamanager/backendbase.h b/kioslave/media/mediamanager/backendbase.h
new file mode 100644
index 000000000..689522d1f
--- /dev/null
+++ b/kioslave/media/mediamanager/backendbase.h
@@ -0,0 +1,35 @@
+/* This file is part of the KDE Project
+ Copyright (c) 2004 Kvin Ottens <ervin ipsquad net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef _BACKENDBASE_H_
+#define _BACKENDBASE_H_
+
+#include "medialist.h"
+
+class BackendBase
+{
+protected:
+ BackendBase(MediaList &list);
+public:
+ virtual ~BackendBase() { }
+
+protected:
+ MediaList &m_mediaList;
+};
+
+#endif
diff --git a/kioslave/media/mediamanager/fstabbackend.cpp b/kioslave/media/mediamanager/fstabbackend.cpp
new file mode 100644
index 000000000..4ffcf4b2d
--- /dev/null
+++ b/kioslave/media/mediamanager/fstabbackend.cpp
@@ -0,0 +1,483 @@
+/* This file is part of the KDE Project
+ Copyright (c) 2004 Kévin Ottens <ervin ipsquad net>
+ Linux CD/DVD detection
+ Copyright (c) 2005 Bernhard Rosenkraenzer <bero arklinux org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "fstabbackend.h"
+
+#ifdef __linux__
+// For CD/DVD drive detection
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <stdint.h>
+#define CDROM_GET_CAPABILITY 0x5331
+#define CDSL_CURRENT ((int) (~0U>>1))
+#define CDC_DVD_R 0x10000 /* drive can write DVD-R */
+#define CDC_DVD_RAM 0x20000 /* drive can write DVD-RAM */
+#define CDC_CD_R 0x2000 /* drive is a CD-R */
+#define CDC_CD_RW 0x4000 /* drive is a CD-RW */
+#define CDC_DVD 0x8000 /* drive is a DVD */
+#include <qfile.h>
+#endif
+
+#include <klocale.h>
+#include <kio/job.h>
+#include <kio/netaccess.h>
+#include <kdebug.h>
+#include <kdirwatch.h>
+#include <kurl.h>
+#include <kmountpoint.h>
+#include <kstandarddirs.h>
+
+#ifdef _OS_SOLARIS_
+#define FSTAB "/etc/vfstab"
+#define MTAB "/etc/mnttab"
+#else
+#define FSTAB "/etc/fstab"
+#define MTAB "/etc/mtab"
+#endif
+
+
+
+FstabBackend::FstabBackend(MediaList &list, bool networkSharesOnly)
+ : QObject(), BackendBase(list), m_networkSharesOnly(networkSharesOnly)
+{
+ KDirWatch::self()->addFile(MTAB);
+ KDirWatch::self()->addFile(FSTAB);
+
+ connect( KDirWatch::self(), SIGNAL( dirty(const QString&) ),
+ this, SLOT( slotDirty(const QString&) ) );
+
+ handleFstabChange(false);
+ handleMtabChange(false);
+
+ KDirWatch::self()->startScan();
+
+#ifdef Q_OS_FREEBSD
+ connect( &m_mtabTimer, SIGNAL( timeout() ),
+ this, SLOT( handleMtabChange() ) );
+ m_mtabTimer.start(250);
+#endif
+}
+
+FstabBackend::~FstabBackend()
+{
+ QStringList::iterator it = m_mtabIds.begin();
+ QStringList::iterator end = m_mtabIds.end();
+
+ for (; it!=end; ++it)
+ {
+ m_mediaList.removeMedium(*it, false);
+ }
+
+ it = m_fstabIds.begin();
+ end = m_fstabIds.end();
+
+ for (; it!=end; ++it)
+ {
+ m_mediaList.removeMedium(*it, false);
+ }
+ KDirWatch::self()->removeFile(FSTAB);
+ KDirWatch::self()->removeFile(MTAB);
+}
+
+QString FstabBackend::mount( const QString &_udi )
+{
+ const Medium* medium = m_mediaList.findById(_udi);
+ if (!medium)
+ return i18n("No such medium: %1").arg(_udi);
+ KIO::Job* job = KIO::mount( false, 0, medium->deviceNode(), medium->mountPoint());
+ KIO::NetAccess::synchronousRun( job, 0 );
+ return QString::null;
+}
+
+QString FstabBackend::unmount( const QString &_udi )
+{
+ const Medium* medium = m_mediaList.findById(_udi);
+ if (!medium)
+ return i18n("No such medium: %1").arg(_udi);
+ KIO::Job* job = KIO::unmount( medium->mountPoint(), false);
+ KIO::NetAccess::synchronousRun( job, 0 );
+ return QString::null;
+}
+
+void FstabBackend::slotDirty(const QString &path)
+{
+ if (path==MTAB)
+ {
+ handleMtabChange();
+ }
+ else if (path==FSTAB)
+ {
+ handleFstabChange();
+ }
+}
+
+bool inExclusionPattern(KMountPoint *mount, bool networkSharesOnly)
+{
+ if ( mount->mountType() == "swap"
+ || mount->mountType() == "tmpfs"
+ || mount->mountType() == "sysfs"
+ || mount->mountType() == "fdescfs"
+ || mount->mountType() == "kernfs"
+ || mount->mountType() == "usbfs"
+ || mount->mountType().contains( "proc" )
+ || mount->mountType() == "unknown"
+ || mount->mountType() == "none"
+ || mount->mountType() == "sunrpc"
+ || mount->mountedFrom() == "none"
+ || mount->mountedFrom() == "tmpfs"
+ || mount->mountedFrom().find("shm") != -1
+ || mount->mountPoint() == "/dev/swap"
+ || mount->mountPoint() == "/dev/pts"
+ || mount->mountPoint().find("/proc") == 0
+ || mount->mountPoint().find("/sys") == 0
+
+ // We might want to display only network shares
+ // since HAL doesn't handle them
+ || ( networkSharesOnly
+ && mount->mountType().find( "smb" ) == -1
+ && mount->mountType().find( "cifs" ) == -1
+ && mount->mountType().find( "nfs" ) == -1
+ )
+ )
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+
+void FstabBackend::handleMtabChange(bool allowNotification)
+{
+ QStringList new_mtabIds;
+ KMountPoint::List mtab = KMountPoint::currentMountPoints();
+
+ KMountPoint::List::iterator it = mtab.begin();
+ KMountPoint::List::iterator end = mtab.end();
+
+ for (; it!=end; ++it)
+ {
+ QString dev = (*it)->mountedFrom();
+ QString mp = (*it)->mountPoint();
+ QString fs = (*it)->mountType();
+
+ if ( ::inExclusionPattern(*it, m_networkSharesOnly) ) continue;
+
+ /* Did we know this already before ? If yes, then
+ nothing has changed, do not stat the mount point. Avoids
+ hang if network shares are stalling */
+ QString mtabEntry = dev + "*" + mp + "*" + fs;
+ if(m_mtabEntries.contains(mtabEntry)) {
+ new_mtabIds += m_mtabEntries[mtabEntry];
+ continue;
+ }
+
+ QString id = generateId(dev, mp);
+ new_mtabIds+=id;
+ m_mtabEntries[mtabEntry] = id;
+
+ if ( !m_mtabIds.contains(id) && m_fstabIds.contains(id) )
+ {
+ QString mime, icon, label;
+ guess(dev, mp, fs, true, mime, icon, label);
+ m_mediaList.changeMediumState(id, true, false,
+ mime, icon, label);
+ }
+#if 0
+ else if ( !m_mtabIds.contains(id) )
+ {
+ QString name = generateName(dev, fs);
+
+ Medium *m = new Medium(id, name);
+
+ m->mountableState(dev, mp, fs, true);
+
+ QString mime, icon, label;
+ guess(dev, mp, fs, true, mime, icon, label);
+
+ m->setMimeType(mime);
+ m->setIconName(icon);
+ m->setLabel(label);
+
+ m_mediaList.addMedium(m, notificationAllowed);
+ }
+#endif
+ }
+
+ QStringList::iterator it2 = m_mtabIds.begin();
+ QStringList::iterator end2 = m_mtabIds.end();
+
+ for (; it2!=end2; ++it2)
+ {
+ if ( !new_mtabIds.contains(*it2) && m_fstabIds.contains(*it2) )
+ {
+ const Medium *medium = m_mediaList.findById(*it2);
+
+ QString dev = medium->deviceNode();
+ QString mp = medium->mountPoint();
+ QString fs = medium->fsType();
+
+
+ QString mtabEntry = dev + "*" + mp + "*" + fs;
+ m_mtabEntries.remove(mtabEntry);
+
+ QString mime, icon, label;
+ guess(dev, mp, fs, false, mime, icon, label);
+
+ m_mediaList.changeMediumState(*it2, false, false,
+ mime, icon, label);
+ }
+#if 0
+ else if ( !new_mtabIds.contains(*it2) )
+ {
+ m_mediaList.removeMedium(*it2, allowNotification);
+ }
+#endif
+ }
+
+ m_mtabIds = new_mtabIds;
+}
+
+void FstabBackend::handleFstabChange(bool allowNotification)
+{
+ QStringList new_fstabIds;
+ KMountPoint::List fstab = KMountPoint::possibleMountPoints();
+
+ KMountPoint::List::iterator it = fstab.begin();
+ KMountPoint::List::iterator end = fstab.end();
+
+ for (; it!=end; ++it)
+ {
+ QString dev = (*it)->mountedFrom();
+ QString mp = (*it)->mountPoint();
+ QString fs = (*it)->mountType();
+
+ if ( ::inExclusionPattern(*it, m_networkSharesOnly) ) continue;
+
+ QString id = generateId(dev, mp);
+ new_fstabIds+=id;
+
+ if ( !m_fstabIds.contains(id) )
+ {
+ QString name = generateName(dev, fs);
+
+ Medium *m = new Medium(id, name);
+
+ m->mountableState(dev, mp, fs, false);
+
+ QString mime, icon, label;
+ guess(dev, mp, fs, false, mime, icon, label);
+
+ m->setMimeType(mime);
+ m->setIconName(icon);
+ m->setLabel(label);
+
+ m_mediaList.addMedium(m, allowNotification);
+ }
+ }
+
+ QStringList::iterator it2 = m_fstabIds.begin();
+ QStringList::iterator end2 = m_fstabIds.end();
+
+ for (; it2!=end2; ++it2)
+ {
+ if ( !new_fstabIds.contains(*it2) )
+ {
+ m_mediaList.removeMedium(*it2, allowNotification);
+ }
+ }
+
+ m_fstabIds = new_fstabIds;
+}
+
+QString FstabBackend::generateId(const QString &devNode,
+ const QString &mountPoint)
+{
+ QString d = KStandardDirs::realFilePath(devNode);
+ QString m = KStandardDirs::realPath(mountPoint);
+
+ return "/org/kde/mediamanager/fstab/"
+ +d.replace("/", "")
+ +m.replace("/", "");
+}
+
+QString FstabBackend::generateName(const QString &devNode, const QString &fsType)
+{
+ KURL url( devNode );
+
+ if ( url.isValid() )
+ {
+ return url.fileName();
+ }
+ else // surely something nfs or samba based
+ {
+ return fsType;
+ }
+}
+
+void FstabBackend::guess(const QString &devNode, const QString &mountPoint,
+ const QString &fsType, bool mounted,
+ QString &mimeType, QString &iconName, QString &label)
+{
+ enum { UNKNOWN, CD, CDWRITER, DVD, DVDWRITER } devType = UNKNOWN;
+#ifdef __linux__
+ // Guessing device types by mount point is not exactly accurate...
+ // Do something accurate first, and fall back if necessary.
+ int device=open(QFile::encodeName(devNode), O_RDONLY|O_NONBLOCK);
+ if(device>=0)
+ {
+ bool isCd=false;
+ QString devname=devNode.section('/', -1);
+ if(devname.startsWith("scd") || devname.startsWith("sr"))
+ {
+ // SCSI CD/DVD drive
+ isCd=true;
+ }
+ else if(devname.startsWith("hd"))
+ {
+ // IDE device -- we can't tell if this is a
+ // CD/DVD drive or harddisk by just looking at the
+ // filename
+ QFile m(QString("/proc/ide/") + devname + "/media");
+ if(m.open(IO_ReadOnly))
+ {
+ QString buf;
+ m.readLine(buf, 1024);
+ if(buf.contains("cdrom"))
+ isCd=true;
+ m.close();
+ }
+ }
+ if(isCd)
+ {
+ int drv=ioctl(device, CDROM_GET_CAPABILITY, CDSL_CURRENT);
+ if(drv>=0)
+ {
+ if((drv & CDC_DVD_R) || (drv & CDC_DVD_RAM))
+ devType = DVDWRITER;
+ else if((drv & CDC_CD_R) || (drv & CDC_CD_RW))
+ devType = CDWRITER;
+ else if(drv & CDC_DVD)
+ devType = DVD;
+ else
+ devType = CD;
+ }
+ }
+ close(device);
+ }
+#endif
+ if ( devType == CDWRITER
+ || devNode.find("cdwriter")!=-1 || mountPoint.find("cdwriter")!=-1
+ || devNode.find("cdrecorder")!=-1 || mountPoint.find("cdrecorder")!=-1
+ || devNode.find("cdburner")!=-1 || mountPoint.find("cdburner")!=-1
+ || devNode.find("cdrw")!=-1 || mountPoint.find("cdrw")!=-1
+ || devNode.find("graveur")!=-1
+ )
+ {
+ mimeType = "media/cdwriter";
+ label = i18n("CD Recorder");
+ }
+ else if ( devType == DVD || devType == DVDWRITER
+ || devNode.find("dvd")!=-1 || mountPoint.find("dvd")!=-1 )
+ {
+ mimeType = "media/dvd";
+ label = i18n("DVD");
+ }
+ else if ( devType == CD
+ || devNode.find("cdrom")!=-1 || mountPoint.find("cdrom")!=-1
+ // LINUX SPECIFIC
+ || devNode.find("/dev/scd")!=-1 || devNode.find("/dev/sr")!=-1
+ // FREEBSD SPECIFIC
+ || devNode.find("/acd")!=-1 || devNode.find("/scd")!=-1
+ )
+ {
+ mimeType = "media/cdrom";
+ label = i18n("CD-ROM");
+ }
+ else if ( devNode.find("fd")!=-1 || mountPoint.find("fd")!=-1
+ || devNode.find("floppy")!=-1 || mountPoint.find("floppy")!=-1 )
+ {
+ if ( devNode.find("360")!=-1 || devNode.find("1200")!=-1 )
+ {
+ mimeType = "media/floppy5";
+ }
+ else
+ {
+ mimeType = "media/floppy";
+ }
+ label = i18n("Floppy");
+ }
+ else if ( mountPoint.find("zip")!=-1
+ // FREEBSD SPECIFIC
+ || devNode.find("/afd")!=-1
+ )
+ {
+ mimeType = "media/zip";
+ label = i18n("Zip Disk");
+ }
+ else if ( mountPoint.find("removable")!=-1
+ || mountPoint.find("hotplug")!=-1
+ || mountPoint.find("usb")!=-1
+ || mountPoint.find("firewire")!=-1
+ || mountPoint.find("ieee1394")!=-1
+ || devNode.find("/usb/")!= -1
+ )
+ {
+ mimeType = "media/removable";
+ label = i18n("Removable Device");
+ }
+ else if ( fsType.find("nfs")!=-1 )
+ {
+ mimeType = "media/nfs";
+ label = i18n("Remote Share");
+ }
+ else if ( fsType.find("smb")!=-1 || fsType.find("cifs")!=-1
+ || devNode.find("//")!=-1 )
+ {
+ mimeType = "media/smb";
+ label = i18n("Remote Share");
+ }
+ else
+ {
+ mimeType = "media/hdd";
+ label = i18n("Hard Disk");
+ }
+
+ if ( mimeType=="media/nfs" || mimeType=="media/smb" )
+ {
+ label+= " (" + devNode + ")";
+ }
+ else
+ {
+ QString tmp = devNode;
+ if ( tmp.startsWith("/dev/") )
+ {
+ tmp = tmp.mid(5);
+ }
+ label+= " (" + tmp + ")";
+ }
+ mimeType+= (mounted ? "_mounted" : "_unmounted");
+ iconName = QString::null;
+}
+
+#include "fstabbackend.moc"
diff --git a/kioslave/media/mediamanager/fstabbackend.h b/kioslave/media/mediamanager/fstabbackend.h
new file mode 100644
index 000000000..ceb2f23ef
--- /dev/null
+++ b/kioslave/media/mediamanager/fstabbackend.h
@@ -0,0 +1,68 @@
+/* This file is part of the KDE Project
+ Copyright (c) 2004 Kvin Ottens <ervin ipsquad net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef _FSTABBACKEND_H_
+#define _FSTABBACKEND_H_
+
+#include "backendbase.h"
+
+#include <qobject.h>
+#include <qstringlist.h>
+#include <qmap.h>
+
+#ifdef Q_OS_FREEBSD
+#include <qtimer.h>
+#endif
+
+class FstabBackend : public QObject, public BackendBase
+{
+Q_OBJECT
+
+public:
+ FstabBackend(MediaList &list, bool networkSharesOnly = false);
+ virtual ~FstabBackend();
+
+ static void guess(const QString &devNode, const QString &mountPoint,
+ const QString &fsType, bool mounted,
+ QString &mimeType, QString &iconName,
+ QString &label);
+
+ QString mount(const QString &id);
+ QString unmount(const QString &id);
+
+private slots:
+ void slotDirty(const QString &path);
+ void handleFstabChange(bool allowNotification = true);
+ void handleMtabChange(bool allowNotification = true);
+
+private:
+ static QString generateId(const QString &devNode,
+ const QString &mountPoint);
+ static QString generateName(const QString &devNode,
+ const QString &fsType);
+
+ bool m_networkSharesOnly;
+ QStringList m_mtabIds;
+ QMap<QString, QString> m_mtabEntries;
+ QStringList m_fstabIds;
+#ifdef Q_OS_FREEBSD
+ QTimer m_mtabTimer;
+#endif
+};
+
+#endif
diff --git a/kioslave/media/mediamanager/halbackend.cpp b/kioslave/media/mediamanager/halbackend.cpp
new file mode 100644
index 000000000..65c796605
--- /dev/null
+++ b/kioslave/media/mediamanager/halbackend.cpp
@@ -0,0 +1,1345 @@
+/* This file is part of the KDE Project
+ Copyright (c) 2004-2005 Jérôme Lodewyck <jerome dot lodewyck at normalesup dot org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "halbackend.h"
+#include "linuxcdpolling.h"
+
+#include <stdlib.h>
+
+#include <kapplication.h>
+#include <qeventloop.h>
+#include <qfile.h>
+#include <klocale.h>
+#include <kurl.h>
+#include <kdebug.h>
+#include <kprocess.h>
+#include <kconfig.h>
+#include <qstylesheet.h>
+#include <kmountpoint.h>
+#include <kmessagebox.h>
+#include <kio/job.h>
+
+#define MOUNT_SUFFIX (libhal_volume_is_mounted(halVolume) ? QString("_mounted") : QString("_unmounted"))
+#define MOUNT_ICON_SUFFIX (libhal_volume_is_mounted(halVolume) ? QString("_mount") : QString("_unmount"))
+
+/* Static instance of this class, for static HAL callbacks */
+static HALBackend* s_HALBackend;
+
+/* A macro function to convert HAL string properties to QString */
+QString libhal_device_get_property_QString(LibHalContext *ctx, const char* udi, const char *key)
+{
+ char* _ppt_string;
+ QString _ppt_QString;
+ DBusError error;
+ dbus_error_init(&error);
+ _ppt_string = libhal_device_get_property_string(ctx, udi, key, &error);
+ if ( _ppt_string )
+ _ppt_QString = _ppt_string;
+ libhal_free_string(_ppt_string);
+ return _ppt_QString;
+}
+
+/* Constructor */
+HALBackend::HALBackend(MediaList &list, QObject* parent)
+ : QObject()
+ , BackendBase(list)
+ , m_halContext(NULL)
+ , m_halStoragePolicy(NULL)
+ , m_parent(parent)
+{
+ s_HALBackend = this;
+}
+
+/* Destructor */
+HALBackend::~HALBackend()
+{
+ /* Close HAL connection */
+ if (m_halContext)
+ {
+ const QPtrList<Medium> medlist = m_mediaList.list();
+ QPtrListIterator<Medium> it (medlist);
+ for ( const Medium *current_medium = it.current(); current_medium; current_medium = ++it)
+ {
+ if( !current_medium->id().startsWith( "/org/kde" ))
+ unmount(current_medium->id());
+ }
+
+
+ /* Remove all the registered media first */
+ int numDevices;
+ char** halDeviceList = libhal_get_all_devices( m_halContext, &numDevices, NULL );
+
+ if ( halDeviceList )
+ {
+ for ( int i = 0; i < numDevices; i++ )
+ {
+ m_mediaList.removeMedium( halDeviceList[i], false );
+ }
+ }
+
+ libhal_free_string_array( halDeviceList );
+
+ DBusError error;
+ dbus_error_init(&error);
+ libhal_ctx_shutdown(m_halContext, &error);
+ libhal_ctx_free(m_halContext);
+ }
+
+ if (m_halStoragePolicy)
+ libhal_storage_policy_free(m_halStoragePolicy);
+}
+
+/* Connect to the HAL */
+bool HALBackend::InitHal()
+{
+ kdDebug(1219) << "Context new" << endl;
+ m_halContext = libhal_ctx_new();
+ if (!m_halContext)
+ {
+ kdDebug(1219) << "Failed to initialize HAL!" << endl;
+ return false;
+ }
+
+ // Main loop integration
+ kdDebug(1219) << "Main loop integration" << endl;
+ DBusError error;
+ dbus_error_init(&error);
+ dbus_connection = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
+
+ if (!dbus_connection || dbus_error_is_set(&error)) {
+ dbus_error_free(&error);
+ libhal_ctx_free(m_halContext);
+ m_halContext = NULL;
+ return false;
+ }
+
+ dbus_connection_set_exit_on_disconnect (dbus_connection, FALSE);
+
+ MainLoopIntegration(dbus_connection);
+ libhal_ctx_set_dbus_connection(m_halContext, dbus_connection);
+
+ // HAL callback functions
+ kdDebug(1219) << "Callback functions" << endl;
+ libhal_ctx_set_device_added(m_halContext, HALBackend::hal_device_added);
+ libhal_ctx_set_device_removed(m_halContext, HALBackend::hal_device_removed);
+ libhal_ctx_set_device_new_capability (m_halContext, NULL);
+ libhal_ctx_set_device_lost_capability (m_halContext, NULL);
+ libhal_ctx_set_device_property_modified (m_halContext, HALBackend::hal_device_property_modified);
+ libhal_ctx_set_device_condition(m_halContext, HALBackend::hal_device_condition);
+
+ kdDebug(1219) << "Context Init" << endl;
+ if (!libhal_ctx_init(m_halContext, &error))
+ {
+ if (dbus_error_is_set(&error))
+ dbus_error_free(&error);
+ libhal_ctx_free(m_halContext);
+ m_halContext = NULL;
+ kdDebug(1219) << "Failed to init HAL context!" << endl;
+ return false;
+ }
+
+ /** @todo customize watch policy */
+ kdDebug(1219) << "Watch properties" << endl;
+ if (!libhal_device_property_watch_all(m_halContext, &error))
+ {
+ kdDebug(1219) << "Failed to watch HAL properties!" << endl;
+ return false;
+ }
+
+ /* libhal-storage initialization */
+ kdDebug(1219) << "Storage Policy" << endl;
+ m_halStoragePolicy = libhal_storage_policy_new();
+ /** @todo define libhal-storage icon policy */
+
+ /* List devices at startup */
+ return ListDevices();
+}
+
+/* List devices (at startup)*/
+bool HALBackend::ListDevices()
+{
+ kdDebug(1219) << "ListDevices" << endl;
+
+ int numDevices;
+ char** halDeviceList = libhal_get_all_devices(m_halContext, &numDevices, NULL);
+
+ if (!halDeviceList)
+ return false;
+
+ kdDebug(1219) << "HALBackend::ListDevices : " << numDevices << " devices found" << endl;
+ for (int i = 0; i < numDevices; i++)
+ AddDevice(halDeviceList[i], false);
+
+ libhal_free_string_array( halDeviceList );
+
+ return true;
+}
+
+/* Create a media instance for the HAL device "udi".
+ This functions checks whether the device is worth listing */
+void HALBackend::AddDevice(const char *udi, bool allowNotification)
+{
+ /* We don't deal with devices that do not expose their capabilities.
+ If we don't check this, we will get a lot of warning messages from libhal */
+ if (!libhal_device_property_exists(m_halContext, udi, "info.capabilities", NULL))
+ return;
+
+ /* If the device is already listed, do not process.
+ This should not happen, but who knows... */
+ /** @todo : refresh properties instead ? */
+ if (m_mediaList.findById(udi))
+ return;
+
+ if (libhal_device_get_property_bool(m_halContext, "/org/freedesktop/Hal/devices/computer", "storage.disable_volume_handling", NULL))
+ allowNotification=false;
+
+ /* Add volume block devices */
+ if (libhal_device_query_capability(m_halContext, udi, "volume", NULL))
+ {
+ /* We only list volume that have a filesystem or volume that have an audio track*/
+ if ( libhal_device_get_property_QString(m_halContext, udi, "volume.fsusage") != "filesystem" &&
+ !libhal_device_get_property_bool(m_halContext, udi, "volume.disc.has_audio", NULL) &&
+ !libhal_device_get_property_bool(m_halContext, udi, "volume.disc.is_blank", NULL) )
+ return;
+
+ /* Query drive udi */
+ QString driveUdi = libhal_device_get_property_QString(m_halContext, udi, "block.storage_device");
+ if ( driveUdi.isNull() ) // no storage - no fun
+ return;
+
+ // if the device is locked do not act upon it
+ if (libhal_device_get_property_bool(m_halContext, driveUdi.ascii(), "info.locked", NULL))
+ allowNotification=false;
+
+ // if the device is locked do not act upon it
+ if (libhal_device_get_property_bool(m_halContext, driveUdi.ascii(), "storage.partition_table_changed", NULL))
+ allowNotification=false;
+
+ /** @todo check exclusion list **/
+
+ /* Create medium */
+ Medium* medium = new Medium(udi, "");
+ setVolumeProperties(medium);
+
+ if ( isInFstab( medium ).isNull() )
+ {
+ // if it's not mountable by user and not by HAL, don't show it at all
+ if ( ( libhal_device_get_property_QString(m_halContext, udi, "volume.fsusage") == "filesystem" &&
+ !libhal_device_get_property_bool(m_halContext, udi, "volume.is_mounted", NULL ) ) &&
+ ( libhal_device_get_property_bool(m_halContext, udi, "volume.ignore", NULL ) ) )
+ {
+ delete medium;
+ return;
+ }
+ }
+ QMap<QString,QString> options = MediaManagerUtils::splitOptions(mountoptions(udi));
+ kdDebug() << "automount " << options["automount"] << endl;
+ if (options["automount"] == "true" && allowNotification ) {
+ QString error = mount(medium);
+ if (!error.isEmpty())
+ kdDebug() << "error " << error << endl;
+ }
+ m_mediaList.addMedium(medium, allowNotification);
+
+ return;
+ }
+
+ /* Floppy & zip drives */
+ if (libhal_device_query_capability(m_halContext, udi, "storage", NULL))
+ if ((libhal_device_get_property_QString(m_halContext, udi, "storage.drive_type") == "floppy") ||
+ (libhal_device_get_property_QString(m_halContext, udi, "storage.drive_type") == "zip") ||
+ (libhal_device_get_property_QString(m_halContext, udi, "storage.drive_type") == "jaz"))
+ {
+ if (! libhal_device_get_property_bool(m_halContext, udi, "storage.removable.media_available", NULL) )
+ allowNotification = false;
+ /* Create medium */
+ Medium* medium = new Medium(udi, "");
+ // if the storage has a volume, we ignore it
+ if ( setFloppyProperties(medium) )
+ m_mediaList.addMedium(medium, allowNotification);
+ else
+ delete medium;
+ return;
+ }
+
+ /* Camera handled by gphoto2*/
+ if (libhal_device_query_capability(m_halContext, udi, "camera", NULL) &&
+ ((libhal_device_get_property_QString(m_halContext, udi, "camera.access_method")=="ptp") ||
+
+ (libhal_device_property_exists(m_halContext, udi, "camera.libgphoto2.support", NULL) &&
+ libhal_device_get_property_bool(m_halContext, udi, "camera.libgphoto2.support", NULL)))
+ )
+ {
+ /* Create medium */
+ Medium* medium = new Medium(udi, "");
+ setCameraProperties(medium);
+ m_mediaList.addMedium(medium, allowNotification);
+ return;
+ }
+}
+
+void HALBackend::RemoveDevice(const char *udi)
+{
+ m_mediaList.removeMedium(udi, true);
+}
+
+void HALBackend::ModifyDevice(const char *udi, const char* key)
+{
+ const char* mediumUdi = findMediumUdiFromUdi(udi);
+ if (!mediumUdi)
+ return;
+ bool allowNotification = false;
+ if (strcmp(key, "storage.removable.media_available") == 0)
+ allowNotification = libhal_device_get_property_bool(m_halContext, udi, key, NULL);
+ ResetProperties(mediumUdi, allowNotification);
+}
+
+void HALBackend::DeviceCondition(const char* udi, const char* condition)
+{
+ QString conditionName = QString(condition);
+ kdDebug(1219) << "Processing device condition " << conditionName << " for " << udi << endl;
+
+ if (conditionName == "EjectPressed") {
+ const Medium* medium = m_mediaList.findById(udi);
+ if (!medium) {
+ /* the ejectpressed appears on the drive and we need to find the volume */
+ const QPtrList<Medium> medlist = m_mediaList.list();
+ QPtrListIterator<Medium> it (medlist);
+ for ( const Medium *current_medium = it.current(); current_medium; current_medium = ++it)
+ {
+ if( current_medium->id().startsWith( "/org/kde" ))
+ continue;
+ QString driveUdi = libhal_device_get_property_QString(m_halContext, current_medium->id().latin1(), "block.storage_device");
+ if (driveUdi == udi)
+ {
+ medium = current_medium;
+ break;
+ }
+ }
+ }
+ if (medium) {
+ KProcess p;
+ p << "kio_media_mounthelper" << "-e" << medium->name();
+ p.start(KProcess::DontCare);
+ }
+ }
+
+ const char* mediumUdi = findMediumUdiFromUdi(udi);
+ kdDebug() << "findMedumUdiFromUdi " << udi << " returned " << mediumUdi << endl;
+ if (!mediumUdi)
+ return;
+
+ /* TODO: Warn the user that (s)he should unmount devices before unplugging */
+ if (conditionName == "VolumeUnmountForced")
+ ResetProperties(mediumUdi);
+
+ /* Reset properties after mounting */
+ if (conditionName == "VolumeMount")
+ ResetProperties(mediumUdi);
+
+ /* Reset properties after unmounting */
+ if (conditionName == "VolumeUnmount")
+ ResetProperties(mediumUdi);
+
+}
+
+void HALBackend::MainLoopIntegration(DBusConnection *dbusConnection)
+{
+ m_dBusQtConnection = new DBusQt::Connection(m_parent);
+ m_dBusQtConnection->dbus_connection_setup_with_qt_main(dbusConnection);
+}
+
+/******************************************
+ ** Properties attribution **
+ ******************************************/
+
+/* Return the medium udi that should be updated when recieving a call for
+ device udi */
+const char* HALBackend::findMediumUdiFromUdi(const char* udi)
+{
+ /* Easy part : this Udi is already registered as a device */
+ const Medium* medium = m_mediaList.findById(udi);
+ if (medium)
+ return medium->id().ascii();
+
+ /* Hard part : this is a volume whose drive is registered */
+ if (libhal_device_property_exists(m_halContext, udi, "info.capabilities", NULL))
+ if (libhal_device_query_capability(m_halContext, udi, "volume", NULL))
+ {
+ QString driveUdi = libhal_device_get_property_QString(m_halContext, udi, "block.storage_device");
+ return findMediumUdiFromUdi(driveUdi.ascii());
+ }
+
+ return NULL;
+}
+
+void HALBackend::ResetProperties(const char* mediumUdi, bool allowNotification)
+{
+ kdDebug(1219) << "HALBackend::setProperties" << endl;
+ if ( QString::fromLatin1( mediumUdi ).startsWith( "/org/kde/" ) )
+ {
+ const Medium *cmedium = m_mediaList.findById(mediumUdi);
+ if ( cmedium )
+ {
+ Medium m( *cmedium );
+ if ( setFstabProperties( &m ) ) {
+ kdDebug() << "setFstabProperties worked" << endl;
+ m_mediaList.changeMediumState(m, allowNotification);
+ }
+ return;
+ }
+ }
+
+ Medium* m = new Medium(mediumUdi, "");
+
+ if (libhal_device_query_capability(m_halContext, mediumUdi, "volume", NULL))
+ setVolumeProperties(m);
+ if (libhal_device_query_capability(m_halContext, mediumUdi, "storage", NULL))
+ setFloppyProperties(m);
+ if (libhal_device_query_capability(m_halContext, mediumUdi, "camera", NULL))
+ setCameraProperties(m);
+
+ m_mediaList.changeMediumState(*m, allowNotification);
+
+ delete m;
+}
+
+void HALBackend::setVolumeProperties(Medium* medium)
+{
+ kdDebug(1219) << "HALBackend::setVolumeProperties for " << medium->id() << endl;
+
+ const char* udi = medium->id().ascii();
+ /* Check if the device still exists */
+ if (!libhal_device_exists(m_halContext, udi, NULL))
+ return;
+
+ /* Get device information from libhal-storage */
+ LibHalVolume* halVolume = libhal_volume_from_udi(m_halContext, udi);
+ if (!halVolume)
+ return;
+ QString driveUdi = libhal_volume_get_storage_device_udi(halVolume);
+ LibHalDrive* halDrive = 0;
+ if ( !driveUdi.isNull() )
+ halDrive = libhal_drive_from_udi(m_halContext, driveUdi.ascii());
+ if (!halDrive) {
+ // at times HAL sends an UnmountForced event before the device is removed
+ libhal_volume_free(halVolume);
+ return;
+ }
+
+ medium->setName(
+ generateName(libhal_volume_get_device_file(halVolume)) );
+
+ medium->mountableState(
+ libhal_volume_get_device_file(halVolume), /* Device node */
+ libhal_volume_get_mount_point(halVolume), /* Mount point */
+ libhal_volume_get_fstype(halVolume), /* Filesystem type */
+ libhal_volume_is_mounted(halVolume) ); /* Mounted ? */
+
+ char* name = libhal_volume_policy_compute_display_name(halDrive, halVolume, m_halStoragePolicy);
+ QString volume_name = QString::fromUtf8(name);
+ QString media_name = volume_name;
+ medium->setLabel(media_name);
+ free(name);
+
+ QString mimeType;
+ if (libhal_volume_is_disc(halVolume))
+ {
+ mimeType = "media/cdrom" + MOUNT_SUFFIX;
+
+ LibHalVolumeDiscType discType = libhal_volume_get_disc_type(halVolume);
+ if ((discType == LIBHAL_VOLUME_DISC_TYPE_CDROM) ||
+ (discType == LIBHAL_VOLUME_DISC_TYPE_CDR) ||
+ (discType == LIBHAL_VOLUME_DISC_TYPE_CDRW))
+ if (libhal_volume_disc_is_blank(halVolume))
+ {
+ mimeType = "media/blankcd";
+ medium->unmountableState("");
+ }
+ else
+ mimeType = "media/cdwriter" + MOUNT_SUFFIX;
+
+ if ((discType == LIBHAL_VOLUME_DISC_TYPE_DVDROM) || (discType == LIBHAL_VOLUME_DISC_TYPE_DVDRAM) ||
+ (discType == LIBHAL_VOLUME_DISC_TYPE_DVDR) || (discType == LIBHAL_VOLUME_DISC_TYPE_DVDRW) ||
+ (discType == LIBHAL_VOLUME_DISC_TYPE_DVDPLUSR) || (discType == LIBHAL_VOLUME_DISC_TYPE_DVDPLUSRW) )
+ if (libhal_volume_disc_is_blank(halVolume))
+ {
+ mimeType = "media/blankdvd";
+ medium->unmountableState("");
+ }
+ else
+ mimeType = "media/dvd" + MOUNT_SUFFIX;
+
+ if (libhal_volume_disc_has_audio(halVolume) && !libhal_volume_disc_has_data(halVolume))
+ {
+ mimeType = "media/audiocd";
+ medium->unmountableState( "audiocd:/?device=" + QString(libhal_volume_get_device_file(halVolume)) );
+ }
+
+ medium->setIconName(QString::null);
+
+ /* check if the disc id a vcd or a video dvd */
+ DiscType type = LinuxCDPolling::identifyDiscType(libhal_volume_get_device_file(halVolume));
+ switch (type)
+ {
+ case DiscType::VCD:
+ mimeType = "media/vcd";
+ break;
+ case DiscType::SVCD:
+ mimeType = "media/svcd";
+ break;
+ case DiscType::DVD:
+ mimeType = "media/dvdvideo";
+ break;
+ }
+ }
+ else
+ {
+ mimeType = "media/hdd" + MOUNT_SUFFIX;
+ medium->setIconName(QString::null); // reset icon
+ if (libhal_drive_is_hotpluggable(halDrive))
+ {
+ mimeType = "media/removable" + MOUNT_SUFFIX;
+ medium->needMounting();
+ switch (libhal_drive_get_type(halDrive)) {
+ case LIBHAL_DRIVE_TYPE_COMPACT_FLASH:
+ medium->setIconName("compact_flash" + MOUNT_ICON_SUFFIX);
+ break;
+ case LIBHAL_DRIVE_TYPE_MEMORY_STICK:
+ medium->setIconName("memory_stick" + MOUNT_ICON_SUFFIX);
+ break;
+ case LIBHAL_DRIVE_TYPE_SMART_MEDIA:
+ medium->setIconName("smart_media" + MOUNT_ICON_SUFFIX);
+ break;
+ case LIBHAL_DRIVE_TYPE_SD_MMC:
+ medium->setIconName("sd_mmc" + MOUNT_ICON_SUFFIX);
+ break;
+ case LIBHAL_DRIVE_TYPE_PORTABLE_AUDIO_PLAYER:
+ {
+ medium->setIconName("ipod" + MOUNT_ICON_SUFFIX);
+ break;
+ }
+ case LIBHAL_DRIVE_TYPE_CAMERA:
+ {
+ mimeType = "media/camera" + MOUNT_SUFFIX;
+ const char *physdev = libhal_drive_get_physical_device_udi(halDrive);
+ // get model from camera
+ if (physdev && libhal_device_query_capability(m_halContext, physdev, "camera", NULL))
+ {
+ if (libhal_device_property_exists(m_halContext, physdev, "usb_device.product", NULL))
+ medium->setLabel(libhal_device_get_property_QString(m_halContext, physdev, "usb_device.product"));
+ else if (libhal_device_property_exists(m_halContext, physdev, "usb.product", NULL))
+ medium->setLabel(libhal_device_get_property_QString(m_halContext, physdev, "usb.product"));
+ }
+ break;
+ }
+ case LIBHAL_DRIVE_TYPE_TAPE:
+ medium->setIconName(QString::null); //FIXME need icon
+ break;
+ default:
+ medium->setIconName(QString::null);
+ }
+
+ if (medium->isMounted() && QFile::exists(medium->mountPoint() + "/dcim"))
+ {
+ mimeType = "media/camera" + MOUNT_SUFFIX;
+ }
+ }
+ }
+ medium->setMimeType(mimeType);
+
+ libhal_drive_free(halDrive);
+ libhal_volume_free(halVolume);
+}
+
+bool HALBackend::setFstabProperties( Medium *medium )
+{
+ QString mp = isInFstab(medium);
+
+ if (!mp.isNull() && !medium->id().startsWith( "/org/kde" ) )
+ {
+ // now that we know it's in fstab, we have to find out if it's mounted
+ KMountPoint::List mtab = KMountPoint::currentMountPoints();
+
+ KMountPoint::List::iterator it = mtab.begin();
+ KMountPoint::List::iterator end = mtab.end();
+
+ bool mounted = false;
+
+ for (; it!=end; ++it)
+ {
+ if ((*it)->mountedFrom() == medium->deviceNode() && (*it)->mountPoint() == mp )
+ {
+ mounted = true;
+ break;
+ }
+ }
+
+ kdDebug() << mp << " " << mounted << " " << medium->deviceNode() << " " << endl;
+ QString fstype = medium->fsType();
+ if ( fstype.isNull() )
+ fstype = "auto";
+
+ medium->mountableState(
+ medium->deviceNode(),
+ mp, /* Mount point */
+ fstype, /* Filesystem type */
+ mounted ); /* Mounted ? */
+
+ return true;
+ }
+
+ return false;
+
+}
+
+// Handle floppies and zip drives
+bool HALBackend::setFloppyProperties(Medium* medium)
+{
+ kdDebug(1219) << "HALBackend::setFloppyProperties for " << medium->id() << endl;
+
+ const char* udi = medium->id().ascii();
+ /* Check if the device still exists */
+ if (!libhal_device_exists(m_halContext, udi, NULL))
+ return false;
+
+ LibHalDrive* halDrive = libhal_drive_from_udi(m_halContext, udi);
+ if (!halDrive)
+ return false;
+
+ QString drive_type = libhal_device_get_property_QString(m_halContext, udi, "storage.drive_type");
+
+ if (drive_type == "zip") {
+ int numVolumes;
+ char** volumes = libhal_drive_find_all_volumes(m_halContext, halDrive, &numVolumes);
+ libhal_free_string_array(volumes);
+ kdDebug(1219) << " found " << numVolumes << " volumes" << endl;
+ if (numVolumes)
+ {
+ libhal_drive_free(halDrive);
+ return false;
+ }
+ }
+
+ medium->setName( generateName(libhal_drive_get_device_file(halDrive)) );
+ medium->setLabel(i18n("Unknown Drive"));
+
+ // HAL hates floppies - so we have to do it twice ;(
+ medium->mountableState(libhal_drive_get_device_file(halDrive), QString::null, QString::null, false);
+ setFloppyMountState(medium);
+
+ if (drive_type == "floppy")
+ {
+ if (medium->isMounted()) // don't use _SUFFIX here as it accesses the volume
+ medium->setMimeType("media/floppy_mounted" );
+ else
+ medium->setMimeType("media/floppy_unmounted");
+ medium->setLabel(i18n("Floppy Drive"));
+ }
+ else if (drive_type == "zip")
+ {
+ if (medium->isMounted())
+ medium->setMimeType("media/zip_mounted" );
+ else
+ medium->setMimeType("media/zip_unmounted");
+ medium->setLabel(i18n("Zip Drive"));
+ }
+
+ /** @todo And mimtype for JAZ drives ? */
+
+ medium->setIconName(QString::null);
+
+ libhal_drive_free(halDrive);
+
+ return true;
+}
+
+void HALBackend::setFloppyMountState( Medium *medium )
+{
+ if ( !medium->id().startsWith( "/org/kde" ) )
+ {
+ KMountPoint::List mtab = KMountPoint::currentMountPoints();
+ KMountPoint::List::iterator it = mtab.begin();
+ KMountPoint::List::iterator end = mtab.end();
+
+ QString fstype;
+ QString mountpoint;
+ for (; it!=end; ++it)
+ {
+ if ((*it)->mountedFrom() == medium->deviceNode() )
+ {
+ fstype = (*it)->mountType().isNull() ? (*it)->mountType() : "auto";
+ mountpoint = (*it)->mountPoint();
+ medium->mountableState( medium->deviceNode(), mountpoint, fstype, true );
+ return;
+ }
+ }
+ }
+}
+
+void HALBackend::setCameraProperties(Medium* medium)
+{
+ kdDebug(1219) << "HALBackend::setCameraProperties for " << medium->id() << endl;
+
+ const char* udi = medium->id().ascii();
+ /* Check if the device still exists */
+ if (!libhal_device_exists(m_halContext, udi, NULL))
+ return;
+
+ /** @todo find name */
+ medium->setName("camera");
+
+ QString device = "camera:/";
+
+ char *cam = libhal_device_get_property_string(m_halContext, udi, "camera.libgphoto2.name", NULL);
+ DBusError error;
+ dbus_error_init(&error);
+ if (cam &&
+ libhal_device_property_exists(m_halContext, udi, "usb.linux.device_number", NULL) &&
+ libhal_device_property_exists(m_halContext, udi, "usb.bus_number", NULL))
+ device.sprintf("camera://%s@[usb:%03d,%03d]/", cam,
+ libhal_device_get_property_int(m_halContext, udi, "usb.bus_number", &error),
+ libhal_device_get_property_int(m_halContext, udi, "usb.linux.device_number", &error));
+
+ libhal_free_string(cam);
+
+ /** @todo find the rest of this URL */
+ medium->unmountableState(device);
+ medium->setMimeType("media/gphoto2camera");
+ medium->setIconName(QString::null);
+ if (libhal_device_property_exists(m_halContext, udi, "usb_device.product", NULL))
+ medium->setLabel(libhal_device_get_property_QString(m_halContext, udi, "usb_device.product"));
+ else if (libhal_device_property_exists(m_halContext, udi, "usb.product", NULL))
+ medium->setLabel(libhal_device_get_property_QString(m_halContext, udi, "usb.product"));
+ else
+ medium->setLabel(i18n("Camera"));
+}
+
+QString HALBackend::generateName(const QString &devNode)
+{
+ return KURL(devNode).fileName();
+}
+
+/******************************************
+ ** HAL CALL-BACKS **
+ ******************************************/
+
+void HALBackend::hal_device_added(LibHalContext *ctx, const char *udi)
+{
+ kdDebug(1219) << "HALBackend::hal_device_added " << udi << endl;
+ Q_UNUSED(ctx);
+ s_HALBackend->AddDevice(udi);
+}
+
+void HALBackend::hal_device_removed(LibHalContext *ctx, const char *udi)
+{
+ kdDebug(1219) << "HALBackend::hal_device_removed " << udi << endl;
+ Q_UNUSED(ctx);
+ s_HALBackend->RemoveDevice(udi);
+}
+
+void HALBackend::hal_device_property_modified(LibHalContext *ctx, const char *udi,
+ const char *key, dbus_bool_t is_removed, dbus_bool_t is_added)
+{
+ kdDebug(1219) << "HALBackend::hal_property_modified " << udi << " -- " << key << endl;
+ Q_UNUSED(ctx);
+ Q_UNUSED(is_removed);
+ Q_UNUSED(is_added);
+ s_HALBackend->ModifyDevice(udi, key);
+}
+
+void HALBackend::hal_device_condition(LibHalContext *ctx, const char *udi,
+ const char *condition_name,
+ const char* message
+ )
+{
+ kdDebug(1219) << "HALBackend::hal_device_condition " << udi << " -- " << condition_name << endl;
+ Q_UNUSED(ctx);
+ Q_UNUSED(message);
+ s_HALBackend->DeviceCondition(udi, condition_name);
+}
+
+QStringList HALBackend::mountoptions(const QString &name)
+{
+ const Medium* medium = m_mediaList.findById(name);
+ if (medium && !isInFstab(medium).isNull())
+ return QStringList(); // not handled by HAL - fstab entry
+
+ KConfig config("mediamanagerrc");
+ config.setGroup(name);
+
+ char ** array = libhal_device_get_property_strlist(m_halContext, name.latin1(), "volume.mount.valid_options", NULL);
+ QMap<QString,bool> valids;
+
+ for (int index = 0; array && array[index]; ++index) {
+ QString t = array[index];
+ if (t.endsWith("="))
+ t = t.left(t.length() - 1);
+ valids[t] = true;
+ kdDebug() << "valid " << t << endl;
+ }
+ libhal_free_string_array(array);
+ QStringList result;
+ QString tmp;
+
+ QString fstype = libhal_device_get_property_QString(m_halContext, name.latin1(), "volume.fstype");
+ if (fstype.isNull())
+ fstype = libhal_device_get_property_QString(m_halContext, name.latin1(), "volume.policy.mount_filesystem");
+
+ QString drive_udi = libhal_device_get_property_QString(m_halContext, name.latin1(), "block.storage_device");
+
+ bool removable = false;
+ if ( !drive_udi.isNull() )
+ removable = libhal_device_get_property_bool(m_halContext, drive_udi.latin1(), "storage.removable", NULL)
+ || libhal_device_get_property_bool(m_halContext, drive_udi.latin1(), "storage.hotpluggable", NULL);
+
+ config.setGroup(drive_udi);
+ bool value = config.readBoolEntry("automount", false);
+ config.setGroup(name);
+
+ if (libhal_device_get_property_bool(m_halContext, name.latin1(), "volume.disc.is_blank", NULL)
+ || libhal_device_get_property_bool(m_halContext, name.latin1(), "volume.disc.is_vcd", NULL)
+ || libhal_device_get_property_bool(m_halContext, name.latin1(), "volume.disc.is_svcd", NULL)
+ || libhal_device_get_property_bool(m_halContext, name.latin1(), "volume.disc.is_videodvd", NULL)
+ || libhal_device_get_property_bool(m_halContext, name.latin1(), "volume.disc.has_audio", NULL))
+ value = false;
+
+ result << QString("automount=%1").arg(value ? "true" : "false");
+
+ if (valids.contains("ro"))
+ {
+ value = config.readBoolEntry("ro", false);
+ tmp = QString("ro=%1").arg(value ? "true" : "false");
+ if (fstype != "iso9660") // makes no sense
+ result << tmp;
+ }
+
+ if (valids.contains("quiet"))
+ {
+ value = config.readBoolEntry("quiet", false);
+ tmp = QString("quiet=%1").arg(value ? "true" : "false");
+ if (fstype != "iso9660") // makes no sense
+ result << tmp;
+ }
+
+ if (valids.contains("flush"))
+ {
+ value = config.readBoolEntry("flush", fstype.endsWith("fat"));
+ tmp = QString("flush=%1").arg(value ? "true" : "false");
+ result << tmp;
+ }
+
+ if (valids.contains("uid"))
+ {
+ value = config.readBoolEntry("uid", true);
+ tmp = QString("uid=%1").arg(value ? "true" : "false");
+ result << tmp;
+ }
+
+ if (valids.contains("utf8"))
+ {
+ value = config.readBoolEntry("utf8", true);
+ tmp = QString("utf8=%1").arg(value ? "true" : "false");
+ result << tmp;
+ }
+
+ if (valids.contains("shortname"))
+ {
+ QString svalue = config.readEntry("shortname", "lower").lower();
+ if (svalue == "winnt")
+ result << "shortname=winnt";
+ else if (svalue == "win95")
+ result << "shortname=win95";
+ else if (svalue == "mixed")
+ result << "shortname=mixed";
+ else
+ result << "shortname=lower";
+ }
+
+ // pass our locale to the ntfs-3g driver so it can translate local characters
+ if (valids.contains("locale") && fstype == "ntfs-3g")
+ {
+ // have to obtain LC_CTYPE as returned by the `locale` command
+ // check in the same order as `locale` does
+ char *cType;
+ if ( (cType = getenv("LC_ALL")) || (cType = getenv("LC_CTYPE")) || (cType = getenv("LANG")) ) {
+ result << QString("locale=%1").arg(cType);
+ }
+ }
+
+ if (valids.contains("sync"))
+ {
+ value = config.readBoolEntry("sync", ( valids.contains("flush") && !fstype.endsWith("fat") ) && removable);
+ tmp = QString("sync=%1").arg(value ? "true" : "false");
+ if (fstype != "iso9660") // makes no sense
+ result << tmp;
+ }
+
+ if (valids.contains("noatime"))
+ {
+ value = config.readBoolEntry("atime", !fstype.endsWith("fat"));
+ tmp = QString("atime=%1").arg(value ? "true" : "false");
+ if (fstype != "iso9660") // makes no sense
+ result << tmp;
+ }
+
+ QString mount_point = libhal_device_get_property_QString(m_halContext, name.latin1(), "volume.mount_point");
+ if (mount_point.isEmpty())
+ mount_point = libhal_device_get_property_QString(m_halContext, name.latin1(), "volume.policy.desired_mount_point");
+
+ mount_point = config.readEntry("mountpoint", mount_point);
+
+ if (!mount_point.startsWith("/"))
+ mount_point = "/media/" + mount_point;
+
+ result << QString("mountpoint=%1").arg(mount_point);
+ result << QString("filesystem=%1").arg(fstype);
+
+ if (valids.contains("data"))
+ {
+ QString svalue = config.readEntry("journaling").lower();
+ if (svalue == "ordered")
+ result << "journaling=ordered";
+ else if (svalue == "writeback")
+ result << "journaling=writeback";
+ else if (svalue == "data")
+ result << "journaling=data";
+ else
+ result << "journaling=ordered";
+ }
+
+ return result;
+}
+
+bool HALBackend::setMountoptions(const QString &name, const QStringList &options )
+{
+ kdDebug() << "setMountoptions " << name << " " << options << endl;
+
+ KConfig config("mediamanagerrc");
+ config.setGroup(name);
+
+ QMap<QString,QString> valids = MediaManagerUtils::splitOptions(options);
+
+ const char *names[] = { "ro", "quiet", "atime", "uid", "utf8", "flush", "sync", 0 };
+ for (int index = 0; names[index]; ++index)
+ if (valids.contains(names[index]))
+ config.writeEntry(names[index], valids[names[index]] == "true");
+
+ if (valids.contains("shortname"))
+ config.writeEntry("shortname", valids["shortname"]);
+
+ if (valids.contains("journaling"))
+ config.writeEntry("journaling", valids["journaling"]);
+
+ if (!mountoptions(name).contains(QString("mountpoint=%1").arg(valids["mountpoint"])))
+ config.writeEntry("mountpoint", valids["mountpoint"]);
+
+ if (valids.contains("automount")) {
+ QString drive_udi = libhal_device_get_property_QString(m_halContext, name.latin1(), "block.storage_device");
+ config.setGroup(drive_udi);
+ config.writeEntry("automount", valids["automount"]);
+ }
+
+ return true;
+}
+
+static QString mount_priv(const char *udi, const char *mount_point, const char **poptions, int noptions,
+ DBusConnection *dbus_connection)
+{
+ DBusMessage *dmesg, *reply;
+ DBusError error;
+
+ const char *fstype = "";
+ if (!(dmesg = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
+ "org.freedesktop.Hal.Device.Volume",
+ "Mount"))) {
+ kdDebug() << "mount failed for " << udi << ": could not create dbus message\n";
+ return i18n("Internal Error");
+ }
+
+ if (!dbus_message_append_args (dmesg, DBUS_TYPE_STRING, &mount_point, DBUS_TYPE_STRING, &fstype,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &poptions, noptions,
+ DBUS_TYPE_INVALID))
+ {
+ kdDebug() << "mount failed for " << udi << ": could not append args to dbus message\n";
+ dbus_message_unref (dmesg);
+ return i18n("Internal Error");
+ }
+
+ QString qerror;
+
+ dbus_error_init (&error);
+ if (!(reply = dbus_connection_send_with_reply_and_block (dbus_connection, dmesg, -1, &error)))
+ {
+ QString qerror = error.message;
+ kdError() << "mount failed for " << udi << ": " << error.name << " - " << qerror << endl;
+ if ( !strcmp(error.name, "org.freedesktop.Hal.Device.Volume.UnknownFilesystemType"))
+ qerror = i18n("Invalid filesystem type");
+ else if ( !strcmp(error.name, "org.freedesktop.Hal.Device.Volume.PermissionDenied"))
+ qerror = i18n("Permissions denied");
+ else if ( !strcmp(error.name, "org.freedesktop.Hal.Device.Volume.AlreadyMounted"))
+ qerror = i18n("Device is already mounted.");
+ else if ( !strcmp(error.name, "org.freedesktop.Hal.Device.Volume.InvalidMountpoint") && strlen(mount_point)) {
+ dbus_message_unref (dmesg);
+ dbus_error_free (&error);
+ return mount_priv(udi, "", poptions, noptions, dbus_connection);
+ }
+ dbus_message_unref (dmesg);
+ dbus_error_free (&error);
+ return qerror;
+ }
+
+ kdDebug() << "mount queued for " << udi << endl;
+
+ dbus_message_unref (dmesg);
+ dbus_message_unref (reply);
+
+ return qerror;
+
+}
+
+QString HALBackend::listUsingProcesses(const Medium* medium)
+{
+ QString proclist, fullmsg;
+ QString cmdline = QString("/usr/bin/env fuser -vm %1 2>&1").arg(KProcess::quote(medium->mountPoint()));
+ FILE *fuser = popen(cmdline.latin1(), "r");
+
+ uint counter = 0;
+ if (fuser) {
+ proclist += "<pre>";
+ QTextIStream is(fuser);
+ QString tmp;
+ while (!is.atEnd()) {
+ tmp = is.readLine();
+ tmp = QStyleSheet::escape(tmp) + "\n";
+
+ proclist += tmp;
+ if (counter++ > 10)
+ {
+ proclist += "...";
+ break;
+ }
+ }
+ proclist += "</pre>";
+ (void)pclose( fuser );
+ }
+ if (counter) {
+ fullmsg = i18n("Moreover, programs still using the device "
+ "have been detected. They are listed below. You have to "
+ "close them or change their working directory before "
+ "attempting to unmount the device again.");
+ fullmsg += "<br>" + proclist;
+ return fullmsg;
+ } else {
+ return QString::null;
+ }
+}
+
+void HALBackend::slotResult(KIO::Job *job)
+{
+ kdDebug() << "slotResult " << mount_jobs[job] << endl;
+
+ struct mount_job_data *data = mount_jobs[job];
+ QString& qerror = data->errorMessage;
+ const Medium* medium = data->medium;
+
+ if (job->error() == KIO::ERR_COULD_NOT_UNMOUNT) {
+ QString proclist(listUsingProcesses(medium));
+
+ qerror = "<qt>";
+ qerror += "<p>" + i18n("Unfortunately, the device <b>%1</b> (%2) named <b>'%3'</b> and "
+ "currently mounted at <b>%4</b> could not be unmounted. ").arg(
+ "system:/media/" + medium->name(),
+ medium->deviceNode(),
+ medium->prettyLabel(),
+ medium->prettyBaseURL().pathOrURL()) + "</p>";
+ qerror += "<p>" + i18n("The following error was returned by umount command:");
+ qerror += "</p><pre>" + job->errorText() + "</pre>";
+
+ if (!proclist.isEmpty()) {
+ qerror += proclist;
+ }
+ qerror += "</qt>";
+ } else if (job->error()) {
+ qerror = job->errorText();
+ }
+
+ ResetProperties( medium->id().latin1() );
+ mount_jobs.remove(job);
+
+ /* Job completed. Notify the caller */
+ data->error = job->error();
+ data->completed = true;
+ kapp->eventLoop()->exitLoop();
+}
+
+QString HALBackend::isInFstab(const Medium *medium)
+{
+ KMountPoint::List fstab = KMountPoint::possibleMountPoints(KMountPoint::NeedMountOptions|KMountPoint::NeedRealDeviceName);
+
+ KMountPoint::List::iterator it = fstab.begin();
+ KMountPoint::List::iterator end = fstab.end();
+
+ for (; it!=end; ++it)
+ {
+ QString reald = (*it)->realDeviceName();
+ if ( reald.endsWith( "/" ) )
+ reald = reald.left( reald.length() - 1 );
+ kdDebug() << "isInFstab -" << medium->deviceNode() << "- -" << reald << "- -" << (*it)->mountedFrom() << "-" << endl;
+ if ((*it)->mountedFrom() == medium->deviceNode() || ( !medium->deviceNode().isEmpty() && reald == medium->deviceNode() ) )
+ {
+ QStringList opts = (*it)->mountOptions();
+ if (opts.contains("user") || opts.contains("users"))
+ return (*it)->mountPoint();
+ }
+ }
+
+ return QString::null;
+}
+
+QString HALBackend::mount(const Medium *medium)
+{
+ if (medium->isMounted())
+ return QString(); // that was easy
+
+ QString mountPoint = isInFstab(medium);
+ if (!mountPoint.isNull())
+ {
+ struct mount_job_data data;
+ data.completed = false;
+ data.medium = medium;
+
+ kdDebug() << "triggering user mount " << medium->deviceNode() << " " << mountPoint << " " << medium->id() << endl;
+ KIO::Job *job = KIO::mount( false, 0, medium->deviceNode(), mountPoint );
+ connect(job, SIGNAL( result (KIO::Job *)),
+ SLOT( slotResult( KIO::Job *)));
+ mount_jobs[job] = &data;
+ // The caller expects the device to be mounted when the function
+ // completes. Thus block until the job completes.
+ while (!data.completed) {
+ kapp->eventLoop()->enterLoop();
+ }
+ // Return the error message (if any) to the caller
+ return (data.error) ? data.errorMessage : QString::null;
+
+ } else if (medium->id().startsWith("/org/kde/") )
+ return i18n("Permissions denied");
+
+ QStringList soptions;
+
+ kdDebug() << "mounting " << medium->id() << "..." << endl;
+
+ QMap<QString,QString> valids = MediaManagerUtils::splitOptions(mountoptions(medium->id()));
+ if (valids["flush"] == "true")
+ soptions << "flush";
+
+ if (valids["uid"] == "true")
+ {
+ soptions << QString("uid=%1").arg(getuid());
+ }
+
+ if (valids["ro"] == "true")
+ soptions << "ro";
+
+ if (valids["atime"] != "true")
+ soptions << "noatime";
+
+ if (valids["quiet"] == "true")
+ soptions << "quiet";
+
+ if (valids["utf8"] == "true")
+ soptions << "utf8";
+
+ if (valids["sync"] == "true")
+ soptions << "sync";
+
+ QString mount_point = valids["mountpoint"];
+ if (mount_point.startsWith("/media/"))
+ mount_point = mount_point.mid(7);
+
+ if (valids.contains("shortname"))
+ {
+ soptions << QString("shortname=%1").arg(valids["shortname"]);
+ }
+
+ if (valids.contains("locale"))
+ {
+ soptions << QString("locale=%1").arg(valids["locale"]);
+ }
+
+ if (valids.contains("journaling"))
+ {
+ QString option = valids["journaling"];
+ if (option == "data")
+ soptions << QString("data=journal");
+ else if (option == "writeback")
+ soptions << QString("data=writeback");
+ else
+ soptions << QString("data=ordered");
+ }
+
+ const char **options = new const char*[soptions.size() + 1];
+ uint noptions = 0;
+ for (QStringList::ConstIterator it = soptions.begin(); it != soptions.end(); ++it, ++noptions)
+ options[noptions] = (*it).latin1();
+ options[noptions] = NULL;
+
+ QString qerror = mount_priv(medium->id().latin1(), mount_point.utf8(), options, noptions, dbus_connection);
+ if (!qerror.isEmpty()) {
+ kdError() << "mounting " << medium->id() << " returned " << qerror << endl;
+ return qerror;
+ }
+
+ medium->setHalMounted(true);
+ ResetProperties(medium->id().latin1());
+
+ return QString();
+}
+
+QString HALBackend::mount(const QString &_udi)
+{
+ const Medium* medium = m_mediaList.findById(_udi);
+ if (!medium)
+ return i18n("No such medium: %1").arg(_udi);
+
+ return mount(medium);
+}
+
+QString HALBackend::unmount(const QString &_udi)
+{
+ const Medium* medium = m_mediaList.findById(_udi);
+ if (!medium)
+ { // now we get fancy: if the udi is no volume, it _might_ be a device with only one
+ // volume on it (think CDs) - so we're so nice to the caller to unmount that volume
+ LibHalDrive* halDrive = libhal_drive_from_udi(m_halContext, _udi.latin1());
+ if (halDrive)
+ {
+ int numVolumes;
+ char** volumes = libhal_drive_find_all_volumes(m_halContext, halDrive, &numVolumes);
+ if (numVolumes == 1)
+ medium = m_mediaList.findById( volumes[0] );
+ }
+ }
+
+ if ( !medium )
+ return i18n("No such medium: %1").arg(_udi);
+
+ if (!medium->isMounted())
+ return QString(); // that was easy
+
+ QString mountPoint = isInFstab(medium);
+ if (!mountPoint.isNull())
+ {
+ struct mount_job_data data;
+ data.completed = false;
+ data.medium = medium;
+
+ kdDebug() << "triggering user unmount " << medium->deviceNode() << " " << mountPoint << endl;
+ KIO::Job *job = KIO::unmount( medium->mountPoint(), false );
+ connect(job, SIGNAL( result (KIO::Job *)),
+ SLOT( slotResult( KIO::Job *)));
+ mount_jobs[job] = &data;
+ // The caller expects the device to be unmounted when the function
+ // completes. Thus block until the job completes.
+ while (!data.completed) {
+ kapp->eventLoop()->enterLoop();
+ }
+ // Return the error message (if any) to the caller
+ return (data.error) ? data.errorMessage : QString::null;
+ }
+
+ DBusMessage *dmesg, *reply;
+ DBusError error;
+ const char *options[2];
+
+ const char *udi = medium->id().latin1();
+ kdDebug() << "unmounting " << udi << "..." << endl;
+
+ dbus_error_init(&error);
+ DBusConnection *dbus_connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
+ if (dbus_error_is_set(&error))
+ {
+ dbus_error_free(&error);
+ return false;
+ }
+
+ if (!(dmesg = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
+ "org.freedesktop.Hal.Device.Volume",
+ "Unmount"))) {
+ kdDebug() << "unmount failed for " << udi << ": could not create dbus message\n";
+ return i18n("Internal Error");
+ }
+
+ options[0] = "force";
+ options[1] = 0;
+
+ if (!dbus_message_append_args (dmesg, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &options, 0,
+ DBUS_TYPE_INVALID))
+ {
+ kdDebug() << "unmount failed for " << udi << ": could not append args to dbus message\n";
+ dbus_message_unref (dmesg);
+ return i18n("Internal Error");
+ }
+
+ dbus_error_init (&error);
+ if (!(reply = dbus_connection_send_with_reply_and_block (dbus_connection, dmesg, -1, &error)))
+ {
+ QString qerror, reason;
+
+ kdDebug() << "unmount failed for " << udi << ": " << error.name << " " << error.message << endl;
+ qerror = "<qt>";
+ qerror += "<p>" + i18n("Unfortunately, the device <b>%1</b> (%2) named <b>'%3'</b> and "
+ "currently mounted at <b>%4</b> could not be unmounted. ").arg(
+ "system:/media/" + medium->name(),
+ medium->deviceNode(),
+ medium->prettyLabel(),
+ medium->prettyBaseURL().pathOrURL()) + "</p>";
+ qerror += "<p>" + i18n("Unmounting failed due to the following error:") + "</p>";
+ if (!strcmp(error.name, "org.freedesktop.Hal.Device.Volume.Busy")) {
+ reason = i18n("Device is Busy:");
+ } else if (!strcmp(error.name, "org.freedesktop.Hal.Device.Volume.NotMounted")) {
+ // this is faking. The error is that the device wasn't mounted by hal (but by the system)
+ reason = i18n("Permissions denied");
+ } else {
+ reason = error.message;
+ }
+ qerror += "<p><b>" + reason + "</b></p>";
+
+ // Include list of processes (if any) using the device in the error message
+ reason = listUsingProcesses(medium);
+ if (!reason.isEmpty()) {
+ qerror += reason;
+ }
+
+ dbus_message_unref (dmesg);
+ dbus_error_free (&error);
+ return qerror;
+ }
+
+ kdDebug() << "unmount queued for " << udi << endl;
+
+ dbus_message_unref (dmesg);
+ dbus_message_unref (reply);
+
+ medium->setHalMounted(false);
+ ResetProperties(udi);
+
+ return QString();
+}
+
+#include "halbackend.moc"
diff --git a/kioslave/media/mediamanager/halbackend.h b/kioslave/media/mediamanager/halbackend.h
new file mode 100644
index 000000000..31c682374
--- /dev/null
+++ b/kioslave/media/mediamanager/halbackend.h
@@ -0,0 +1,228 @@
+/* This file is part of the KDE Project
+ Copyright (c) 2004-2005 Jérôme Lodewyck <jerome dot lodewyck at normalesup dot org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+/**
+* This is a media:/ backend for the freedesktop Hardware Abstraction Layer
+* Usage : create an instance of HALBackend, then call InitHal(). A false
+* result from the later function means that something went wrong and that
+* the backend shall not be used.
+*
+* @author Jérôme Lodewyck <jerome dot lodewyck at normalesup dot org>
+* @short media:/ backend for the HAL
+*/
+
+#ifndef _HALBACKEND_H_
+#define _HALBACKEND_H_
+
+#include "backendbase.h"
+
+#include <qobject.h>
+#include <qstringlist.h>
+#include <qstring.h>
+
+#include <config.h>
+
+/* We acknowledge the the dbus API is unstable */
+#define DBUS_API_SUBJECT_TO_CHANGE
+/* DBus-Qt bindings */
+#include <dbus/connection.h>
+/* HAL libraries */
+#include <libhal.h>
+#include <libhal-storage.h>
+
+namespace KIO {
+ class Job;
+}
+
+class HALBackend : public QObject, public BackendBase
+{
+Q_OBJECT
+
+public:
+ /**
+ * Constructor
+ */
+ HALBackend(MediaList &list, QObject* parent);
+
+ /**
+ * Destructor
+ */
+ ~HALBackend();
+
+ /**
+ * Perform HAL initialization.
+ *
+ * @return true if succeded. If not, rely on some other backend
+ */
+ bool InitHal();
+
+ /**
+ * List all devices and append them to the media device list (called only once, at startup).
+ *
+ * @return true if succeded, false otherwise
+ */
+ bool ListDevices();
+
+ QStringList mountoptions(const QString &id);
+
+ bool setMountoptions(const QString &id, const QStringList &options);
+
+ QString mount(const QString &id);
+ QString mount(const Medium *medium);
+ QString unmount(const QString &id);
+
+private:
+ /**
+ * Append a device in the media list. This function will check if the device
+ * is worth listing.
+ *
+ * @param udi Universal Device Id
+ * @param allowNotification Indicates if this event will be notified to the user
+ */
+ void AddDevice(const char* udi, bool allowNotification=true);
+
+ /**
+ * Remove a device from the device list
+ *
+ * @param udi Universal Device Id
+ */
+ void RemoveDevice(const char* udi);
+
+ /**
+ * A device has changed, update it
+ *
+ * @param udi Universal Device Id
+ */
+ void ModifyDevice(const char *udi, const char* key);
+
+ /**
+ * HAL informed that a special action has occured
+ * (e.g. device unplugged without unmounting)
+ *
+ * @param udi Universal Device Id
+ */
+ void DeviceCondition(const char *udi, const char *condition);
+
+ /**
+ * Integrate the DBus connection within qt main loop
+ */
+ void MainLoopIntegration(DBusConnection *dbusConnection);
+
+/* Set media properties */
+private:
+ /**
+ * Reset properties for the given medium
+ */
+ void ResetProperties(const char* MediumUdi, bool allowNotification=false);
+
+ /**
+ * Find the medium that is concerned with device udi
+ */
+ const char* findMediumUdiFromUdi(const char* udi);
+
+ void setVolumeProperties(Medium* medium);
+ bool setFloppyProperties(Medium* medium);
+ void setFloppyMountState( Medium* medium );
+ bool setFstabProperties(Medium* medium);
+ void setCameraProperties(Medium* medium);
+ QString generateName(const QString &devNode);
+ static QString isInFstab(const Medium *medium);
+ static QString listUsingProcesses(const Medium *medium);
+
+private slots:
+ void slotResult(KIO::Job *job);
+
+/* Hal call-backs -- from gvm*/
+public:
+ /** Invoked when a device is added to the Global Device List.
+ *
+ * @param ctx LibHal context
+ * @param udi Universal Device Id
+ */
+ static void hal_device_added(LibHalContext *ctx, const char *udi);
+
+ /** Invoked when a device is removed from the Global Device List.
+ *
+ * @param ctx LibHal context
+ * @param udi Universal Device Id
+ */
+ static void hal_device_removed(LibHalContext *ctx, const char *udi);
+
+ /** Invoked when a property of a device in the Global Device List is
+ * changed, and we have we have subscribed to changes for that device.
+ *
+ * @param ctx LibHal context
+ * @param udi Univerisal Device Id
+ * @param key Key of property
+ */
+ static void hal_device_property_modified(LibHalContext *ctx, const char *udi, const char *key,
+ dbus_bool_t is_removed, dbus_bool_t is_added);
+
+ /** Type for callback when a non-continuos condition occurs on a device
+ *
+ * @param udi Univerisal Device Id
+ * @param condition_name Name of the condition
+ * @param message D-BUS message with variable parameters depending on condition
+ */
+ static void hal_device_condition(LibHalContext *ctx, const char *udi,
+ const char *condition_name,
+ const char* message
+ );
+
+/* HAL and DBus structures */
+private:
+ /**
+ * The HAL context connecting the whole application to the HAL
+ */
+ LibHalContext* m_halContext;
+
+ /**
+ * libhal-storage HAL policy, e.g. for icon names
+ */
+ LibHalStoragePolicy* m_halStoragePolicy;
+
+ /**
+ * The DBus-Qt bindings connection for mainloop integration
+ */
+ DBusQt::Connection* m_dBusQtConnection;
+
+ /**
+ * Object for the kded module
+ */
+ QObject* m_parent;
+
+ DBusConnection *dbus_connection;
+
+ /**
+ * Data structure for fstab mount/unmount jobs
+ */
+ struct mount_job_data {
+ // [in] Medium, which is being mounted/unmounted by the job
+ const Medium* medium;
+ // [in,out] Should be set to true when the job completes
+ bool completed;
+ // [out] KIO::Error if an error occured during operation. Otherwise, 0
+ int error;
+ // [out] Error message to be displayed to the user
+ QString errorMessage;
+ };
+
+ QMap<KIO::Job *, struct mount_job_data*> mount_jobs;
+};
+
+#endif /* _HALBACKEND_H_ */
diff --git a/kioslave/media/mediamanager/linuxcdpolling.cpp b/kioslave/media/mediamanager/linuxcdpolling.cpp
new file mode 100644
index 000000000..7519023fe
--- /dev/null
+++ b/kioslave/media/mediamanager/linuxcdpolling.cpp
@@ -0,0 +1,585 @@
+/* This file is part of the KDE Project
+ Copyright (c) 2003 Gav Wood <gav kde org>
+ Copyright (c) 2004 Kévin Ottens <ervin ipsquad net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+/* Some code of this file comes from kdeautorun */
+
+#include "linuxcdpolling.h"
+
+#include <qthread.h>
+#include <qmutex.h>
+#include <qfile.h>
+
+#include <kdebug.h>
+
+#include "fstabbackend.h"
+
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+// Never ever include directly a kernel header!
+// #include <linux/cdrom.h>
+// Instead we redefine the necessary (copied from the header)
+
+/* This struct is used by the CDROMREADTOCHDR ioctl */
+struct cdrom_tochdr
+{
+ unsigned char cdth_trk0; /* start track */
+ unsigned char cdth_trk1; /* end track */
+};
+
+#define CDROMREADTOCHDR 0x5305 /* Read TOC header
+ (struct cdrom_tochdr) */
+#define CDROM_DRIVE_STATUS 0x5326 /* Get tray position, etc. */
+#define CDROM_DISC_STATUS 0x5327 /* Get disc type, etc. */
+
+/* drive status possibilities returned by CDROM_DRIVE_STATUS ioctl */
+#define CDS_NO_INFO 0 /* if not implemented */
+#define CDS_NO_DISC 1
+#define CDS_TRAY_OPEN 2
+#define CDS_DRIVE_NOT_READY 3
+#define CDS_DISC_OK 4
+
+/* return values for the CDROM_DISC_STATUS ioctl */
+/* can also return CDS_NO_[INFO|DISC], from above */
+#define CDS_AUDIO 100
+#define CDS_DATA_1 101
+#define CDS_DATA_2 102
+#define CDS_XA_2_1 103
+#define CDS_XA_2_2 104
+#define CDS_MIXED 105
+
+#define CDSL_CURRENT ((int) (~0U>>1))
+
+// -------
+
+
+
+DiscType::DiscType(Type type)
+ : m_type(type)
+{
+}
+
+bool DiscType::isKnownDisc() const
+{
+ return m_type != None
+ && m_type != Unknown
+ && m_type != UnknownType
+ && m_type != Broken;
+}
+
+bool DiscType::isDisc() const
+{
+ return m_type != None
+ && m_type != Unknown
+ && m_type != Broken;
+}
+
+bool DiscType::isNotDisc() const
+{
+ return m_type == None;
+}
+
+bool DiscType::isData() const
+{
+ return m_type == Data;
+}
+
+DiscType::operator int() const
+{
+ return (int)m_type;
+}
+
+
+class PollingThread : public QThread
+{
+public:
+ PollingThread(const QCString &devNode) : m_dev(devNode)
+ {
+ kdDebug(1219) << "PollingThread::PollingThread("
+ << devNode << ")" << endl;
+ m_stop = false;
+ m_currentType = DiscType::None;
+ m_lastPollType = DiscType::None;
+ }
+
+
+ void stop()
+ {
+ QMutexLocker locker(&m_mutex);
+ m_stop = true;
+ }
+
+ bool hasChanged()
+ {
+ QMutexLocker locker(&m_mutex);
+
+ return m_currentType!=m_lastPollType;
+ }
+
+ DiscType type()
+ {
+ QMutexLocker locker(&m_mutex);
+ m_currentType = m_lastPollType;
+ return m_currentType;
+ }
+
+protected:
+ virtual void run()
+ {
+ kdDebug(1219) << "PollingThread(" << m_dev << ") start" << endl;
+ while (!m_stop && m_lastPollType!=DiscType::Broken)
+ {
+ m_mutex.lock();
+ DiscType type = m_lastPollType;
+ m_mutex.unlock();
+
+ type = LinuxCDPolling::identifyDiscType(m_dev, type);
+
+ m_mutex.lock();
+ m_lastPollType = type;
+ m_mutex.unlock();
+
+ msleep(500);
+ }
+ kdDebug(1219) << "PollingThread(" << m_dev << ") stop" << endl;
+ }
+
+private:
+ QMutex m_mutex;
+ bool m_stop;
+ const QCString m_dev;
+ DiscType m_currentType;
+ DiscType m_lastPollType;
+};
+
+
+LinuxCDPolling::LinuxCDPolling(MediaList &list)
+ : QObject(), BackendBase(list)
+{
+ connect(&m_mediaList, SIGNAL(mediumAdded(const QString &,
+ const QString &, bool)),
+ this, SLOT(slotMediumAdded(const QString &)) );
+
+ connect(&m_mediaList, SIGNAL(mediumRemoved(const QString &,
+ const QString &, bool)),
+ this, SLOT(slotMediumRemoved(const QString &)) );
+
+ connect(&m_mediaList, SIGNAL(mediumStateChanged(const QString &,
+ const QString &, bool, bool)),
+ this, SLOT(slotMediumStateChanged(const QString &)) );
+
+ connect(&m_timer, SIGNAL(timeout()), this, SLOT(slotTimeout()));
+}
+
+LinuxCDPolling::~LinuxCDPolling()
+{
+ QMap<QString, PollingThread*>::iterator it = m_threads.begin();
+ QMap<QString, PollingThread*>::iterator end = m_threads.end();
+
+ for(; it!=end; ++it)
+ {
+ PollingThread *thread = it.data();
+ thread->stop();
+ thread->wait();
+ delete thread;
+ }
+}
+
+void LinuxCDPolling::slotMediumAdded(const QString &id)
+{
+ kdDebug(1219) << "LinuxCDPolling::slotMediumAdded(" << id << ")" << endl;
+
+ if (m_threads.contains(id)) return;
+
+ const Medium *medium = m_mediaList.findById(id);
+
+ QString mime = medium->mimeType();
+ kdDebug(1219) << "mime == " << mime << endl;
+
+ if (mime.find("dvd")==-1 && mime.find("cd")==-1) return;
+
+ if (!medium->isMounted())
+ {
+ m_excludeNotification.append( id );
+
+ QCString dev = QFile::encodeName( medium->deviceNode() ).data();
+ PollingThread *thread = new PollingThread(dev);
+ m_threads[id] = thread;
+ thread->start();
+ m_timer.start(500);
+ }
+}
+
+void LinuxCDPolling::slotMediumRemoved(const QString &id)
+{
+ kdDebug(1219) << "LinuxCDPolling::slotMediumRemoved(" << id << ")" << endl;
+
+ if (!m_threads.contains(id)) return;
+
+ PollingThread *thread = m_threads[id];
+ m_threads.remove(id);
+ thread->stop();
+ thread->wait();
+ delete thread;
+
+ m_excludeNotification.remove(id);
+}
+
+void LinuxCDPolling::slotMediumStateChanged(const QString &id)
+{
+ kdDebug(1219) << "LinuxCDPolling::slotMediumStateChanged("
+ << id << ")" << endl;
+
+ const Medium *medium = m_mediaList.findById(id);
+
+ QString mime = medium->mimeType();
+ kdDebug(1219) << "mime == " << mime << endl;
+
+ if (mime.find("dvd")==-1 && mime.find("cd")==-1) return;
+
+ if (!m_threads.contains(id) && !medium->isMounted())
+ {
+ // It is just a mount state change, no need to notify
+ m_excludeNotification.append( id );
+
+ QCString dev = QFile::encodeName( medium->deviceNode() ).data();
+ PollingThread *thread = new PollingThread(dev);
+ m_threads[id] = thread;
+ thread->start();
+ m_timer.start(500);
+ }
+ else if (m_threads.contains(id) && medium->isMounted())
+ {
+ PollingThread *thread = m_threads[id];
+ m_threads.remove(id);
+ thread->stop();
+ thread->wait();
+ delete thread;
+ }
+}
+
+void LinuxCDPolling::slotTimeout()
+{
+ //kdDebug(1219) << "LinuxCDPolling::slotTimeout()" << endl;
+
+ if (m_threads.isEmpty())
+ {
+ m_timer.stop();
+ return;
+ }
+
+ QMap<QString, PollingThread*>::iterator it = m_threads.begin();
+ QMap<QString, PollingThread*>::iterator end = m_threads.end();
+
+ for(; it!=end; ++it)
+ {
+ QString id = it.key();
+ PollingThread *thread = it.data();
+
+ if (thread->hasChanged())
+ {
+ DiscType type = thread->type();
+ const Medium *medium = m_mediaList.findById(id);
+ applyType(type, medium);
+ }
+ }
+}
+
+static QString baseType(const Medium *medium)
+{
+ kdDebug(1219) << "baseType(" << medium->id() << ")" << endl;
+
+ QString devNode = medium->deviceNode();
+ QString mountPoint = medium->mountPoint();
+ QString fsType = medium->fsType();
+ bool mounted = medium->isMounted();
+
+ QString mimeType, iconName, label;
+
+ FstabBackend::guess(devNode, mountPoint, fsType, mounted,
+ mimeType, iconName, label);
+
+ if (devNode.find("dvd")!=-1)
+ {
+ kdDebug(1219) << "=> dvd" << endl;
+ return "dvd";
+ }
+ else
+ {
+ kdDebug(1219) << "=> cd" << endl;
+ return "cd";
+ }
+}
+
+static void restoreEmptyState(MediaList &list, const Medium *medium,
+ bool allowNotification)
+{
+ kdDebug(1219) << "restoreEmptyState(" << medium->id() << ")" << endl;
+
+ QString id = medium->id();
+ QString devNode = medium->deviceNode();
+ QString mountPoint = medium->mountPoint();
+ QString fsType = medium->fsType();
+ bool mounted = medium->isMounted();
+
+ QString mimeType, iconName, label;
+
+ FstabBackend::guess(devNode, mountPoint, fsType, mounted,
+ mimeType, iconName, label);
+
+ list.changeMediumState(id, devNode, mountPoint, fsType, mounted,
+ allowNotification, mimeType, iconName, label);
+}
+
+
+void LinuxCDPolling::applyType(DiscType type, const Medium *medium)
+{
+ kdDebug(1219) << "LinuxCDPolling::applyType(" << type << ", "
+ << medium->id() << ")" << endl;
+
+ QString id = medium->id();
+ QString dev = medium->deviceNode();
+
+ bool notify = !m_excludeNotification.contains(id);
+ m_excludeNotification.remove(id);
+
+ switch (type)
+ {
+ case DiscType::Data:
+ restoreEmptyState(m_mediaList, medium, notify);
+ break;
+ case DiscType::Audio:
+ case DiscType::Mixed:
+ m_mediaList.changeMediumState(id, "audiocd:/?device="+dev,
+ notify, "media/audiocd");
+ break;
+ case DiscType::VCD:
+ m_mediaList.changeMediumState(id, false, notify, "media/vcd");
+ break;
+ case DiscType::SVCD:
+ m_mediaList.changeMediumState(id, false, notify, "media/svcd");
+ break;
+ case DiscType::DVD:
+ m_mediaList.changeMediumState(id, false, notify, "media/dvdvideo");
+ break;
+ case DiscType::Blank:
+ if (baseType(medium)=="dvd")
+ {
+ m_mediaList.changeMediumState(id, false,
+ notify, "media/blankdvd");
+ }
+ else
+ {
+ m_mediaList.changeMediumState(id, false,
+ notify, "media/blankcd");
+ }
+ break;
+ case DiscType::None:
+ case DiscType::Unknown:
+ case DiscType::UnknownType:
+ restoreEmptyState(m_mediaList, medium, false);
+ break;
+ }
+}
+
+DiscType LinuxCDPolling::identifyDiscType(const QCString &devNode,
+ const DiscType &current)
+{
+ //kdDebug(1219) << "LinuxCDPolling::identifyDiscType("
+ // << devNode << ")" << endl;
+
+ int fd;
+ struct cdrom_tochdr th;
+
+ // open the device
+ fd = open(devNode, O_RDONLY | O_NONBLOCK);
+ if (fd < 0) return DiscType::Broken;
+
+ switch (ioctl(fd, CDROM_DRIVE_STATUS, CDSL_CURRENT))
+ {
+ case CDS_DISC_OK:
+ {
+ if (current.isDisc())
+ {
+ close(fd);
+ return current;
+ }
+
+ // see if we can read the disc's table of contents (TOC).
+ if (ioctl(fd, CDROMREADTOCHDR, &th))
+ {
+ close(fd);
+ return DiscType::Blank;
+ }
+
+ // read disc status info
+ int status = ioctl(fd, CDROM_DISC_STATUS, CDSL_CURRENT);
+
+ // release the device
+ close(fd);
+
+ switch (status)
+ {
+ case CDS_AUDIO:
+ return DiscType::Audio;
+ case CDS_DATA_1:
+ case CDS_DATA_2:
+ if (hasDirectory(devNode, "video_ts"))
+ {
+ return DiscType::DVD;
+ }
+ else if (hasDirectory(devNode, "vcd"))
+ {
+ return DiscType::VCD;
+ }
+ else if (hasDirectory(devNode, "svcd"))
+ {
+ return DiscType::SVCD;
+ }
+ else
+ {
+ return DiscType::Data;
+ }
+ case CDS_MIXED:
+ return DiscType::Mixed;
+ default:
+ return DiscType::UnknownType;
+ }
+ }
+ case CDS_NO_INFO:
+ close(fd);
+ return DiscType::Unknown;
+ default:
+ close(fd);
+ return DiscType::None;
+ }
+}
+
+bool LinuxCDPolling::hasDirectory(const QCString &devNode, const QCString &dir)
+{
+ bool ret = false; // return value
+ int fd = 0; // file descriptor for drive
+ unsigned short bs; // the discs block size
+ unsigned short ts; // the path table size
+ unsigned int tl; // the path table location (in blocks)
+ unsigned char len_di = 0; // length of the directory name in current path table entry
+ unsigned int parent = 0; // the number of the parent directory's path table entry
+ char dirname[256]; // filename for the current path table entry
+ int pos = 0; // our position into the path table
+ int curr_record = 1; // the path table record we're on
+ QCString fixed_directory = dir.upper(); // the uppercase version of the "directory" parameter
+
+ // open the drive
+ fd = open(devNode, O_RDONLY | O_NONBLOCK);
+ if (fd == -1) return false;
+
+ // read the block size
+ lseek(fd, 0x8080, SEEK_CUR);
+ if (read(fd, &bs, 2) != 2)
+ {
+ close(fd);
+ return false;
+ }
+ if (Q_BYTE_ORDER != Q_LITTLE_ENDIAN)
+ bs = ((bs << 8) & 0xFF00) | ((bs >> 8) & 0xFF);
+
+ // read in size of path table
+ lseek(fd, 2, SEEK_CUR);
+ if (read(fd, &ts, 2) != 2)
+ {
+ close(fd);
+ return false;
+ }
+ if (Q_BYTE_ORDER != Q_LITTLE_ENDIAN)
+ ts = ((ts << 8) & 0xFF00) | ((ts >> 8) & 0xFF);
+
+ // read in which block path table is in
+ lseek(fd, 6, SEEK_CUR);
+ if (read(fd, &tl, 4) != 4)
+ {
+ close(fd);
+ return false;
+ }
+ if (Q_BYTE_ORDER != Q_LITTLE_ENDIAN)
+ tl = ((tl << 24) & 0xFF000000) | ((tl << 8) & 0xFF0000) |
+ ((tl >> 8) & 0xFF00) | ((tl >> 24) & 0xFF);
+
+ // seek to the path table
+ lseek(fd, bs * tl, SEEK_SET);
+
+ // loop through the path table entries
+ while (pos < ts)
+ {
+ // get the length of the filename of the current entry
+ if (read(fd, &len_di, 1) != 1)
+ {
+ ret = false;
+ break;
+ }
+
+ // get the record number of this entry's parent
+ // i'm pretty sure that the 1st entry is always the top directory
+ lseek(fd, 5, SEEK_CUR);
+ if (read(fd, &parent, 2) != 2)
+ {
+ ret = false;
+ break;
+ }
+ if (Q_BYTE_ORDER != Q_LITTLE_ENDIAN)
+ parent = ((parent << 8) & 0xFF00) | ((parent >> 8) & 0xFF);
+
+ // read the name
+ if (read(fd, dirname, len_di) != len_di)
+ {
+ ret = false;
+ break;
+ }
+ dirname[len_di] = 0;
+ qstrcpy(dirname, QCString(dirname).upper());
+
+ // if we found a folder that has the root as a parent, and the directory name matches
+ // then return success
+ if ((parent == 1) && (dirname == fixed_directory))
+ {
+ ret = true;
+ break;
+ }
+
+ // all path table entries are padded to be even, so if this is an odd-length table, seek a byte to fix it
+ if (len_di%2 == 1)
+ {
+ lseek(fd, 1, SEEK_CUR);
+ pos++;
+ }
+
+ // update our position
+ pos += 8 + len_di;
+ curr_record++;
+ }
+
+ close(fd);
+ return ret;
+}
+
+
+#include "linuxcdpolling.moc"
diff --git a/kioslave/media/mediamanager/linuxcdpolling.h b/kioslave/media/mediamanager/linuxcdpolling.h
new file mode 100644
index 000000000..1df113962
--- /dev/null
+++ b/kioslave/media/mediamanager/linuxcdpolling.h
@@ -0,0 +1,86 @@
+/* This file is part of the KDE Project
+ Copyright (c) 2004 Kvin Ottens <ervin ipsquad net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef _LINUXCDPOLLING_H_
+#define _LINUXCDPOLLING_H_
+
+#include "backendbase.h"
+
+#include <qobject.h>
+#include <qcstring.h>
+#include <qmap.h>
+#include <qtimer.h>
+
+class DiscType
+{
+public:
+ enum Type { None, Unknown, Audio, Data, DVD, Mixed,
+ Blank, VCD, SVCD, UnknownType, Broken };
+
+ DiscType(Type type = Unknown);
+
+ bool isKnownDisc() const;
+ bool isDisc() const;
+ bool isNotDisc() const;
+ bool isData() const;
+
+ operator int() const;
+
+private:
+ Type m_type;
+};
+
+class PollingThread;
+
+class LinuxCDPolling : public QObject, public BackendBase
+{
+Q_OBJECT
+
+public:
+
+ LinuxCDPolling(MediaList &list);
+ virtual ~LinuxCDPolling();
+
+ /**
+ * Find the disc type of the medium inserted in a drive
+ * (considered to be a cdrom or dvdrom)
+ *
+ * @param devNode the path to the device to test
+ * @param current the current known state of the drive
+ * @return the disc type
+ */
+ static DiscType identifyDiscType(const QCString &devNode,
+ const DiscType &current = DiscType::Unknown);
+
+private slots:
+ void slotMediumAdded(const QString &id);
+ void slotMediumRemoved(const QString &id);
+ void slotMediumStateChanged(const QString &id);
+ void slotTimeout();
+
+private:
+ void applyType(DiscType type, const Medium *medium);
+
+ static bool hasDirectory(const QCString &devNode, const QCString &dir);
+
+ QMap<QString, PollingThread*> m_threads;
+ QStringList m_excludeNotification;
+ QTimer m_timer;
+};
+
+#endif
diff --git a/kioslave/media/mediamanager/mediadirnotify.cpp b/kioslave/media/mediamanager/mediadirnotify.cpp
new file mode 100644
index 000000000..340414634
--- /dev/null
+++ b/kioslave/media/mediamanager/mediadirnotify.cpp
@@ -0,0 +1,124 @@
+/* This file is part of the KDE Project
+ Copyright (c) 2004 Kévin Ottens <ervin ipsquad net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "mediadirnotify.h"
+
+#include <kdebug.h>
+
+#include <kdirnotify_stub.h>
+
+#include "medium.h"
+
+MediaDirNotify::MediaDirNotify(const MediaList &list)
+ : m_mediaList(list)
+{
+
+}
+
+KURL::List MediaDirNotify::toMediaURL(const KURL &url)
+{
+ kdDebug(1219) << "MediaDirNotify::toMediaURL(" << url << ")" << endl;
+
+ KURL::List result;
+
+ const QPtrList<Medium> list = m_mediaList.list();
+
+ QPtrList<Medium>::const_iterator it = list.begin();
+ QPtrList<Medium>::const_iterator end = list.end();
+
+ for (; it!=end; ++it)
+ {
+ const Medium *m = *it;
+ KURL base = m->prettyBaseURL();
+
+ if ( base.isParentOf(url) )
+ {
+ QString path = KURL::relativePath(base.path(),
+ url.path());
+
+ KURL new_url("media:/"+m->name()+"/"+path );
+ new_url.cleanPath();
+
+ result.append(new_url);
+ }
+ }
+
+ kdDebug(1219) << result << endl;
+ return result;
+}
+
+KURL::List MediaDirNotify::toMediaURLList(const KURL::List &list)
+{
+ KURL::List new_list;
+
+ KURL::List::const_iterator it = list.begin();
+ KURL::List::const_iterator end = list.end();
+
+ for (; it!=end; ++it)
+ {
+ KURL::List urls = toMediaURL(*it);
+
+ if (!urls.isEmpty())
+ {
+ new_list += urls;
+ }
+ }
+
+ return new_list;
+}
+
+ASYNC MediaDirNotify::FilesAdded(const KURL &directory)
+{
+ KURL::List new_urls = toMediaURL(directory);
+
+ if (!new_urls.isEmpty())
+ {
+ KDirNotify_stub notifier("*", "*");
+
+ KURL::List::const_iterator it = new_urls.begin();
+ KURL::List::const_iterator end = new_urls.end();
+
+ for (; it!=end; ++it)
+ {
+ notifier.FilesAdded(*it);
+ }
+ }
+}
+
+ASYNC MediaDirNotify::FilesRemoved(const KURL::List &fileList)
+{
+ KURL::List new_list = toMediaURLList(fileList);
+
+ if (!new_list.isEmpty())
+ {
+ KDirNotify_stub notifier("*", "*");
+ notifier.FilesRemoved( new_list );
+ }
+}
+
+ASYNC MediaDirNotify::FilesChanged(const KURL::List &fileList)
+{
+ KURL::List new_list = toMediaURLList(fileList);
+
+ if (!new_list.isEmpty())
+ {
+ KDirNotify_stub notifier("*", "*");
+ notifier.FilesChanged( new_list );
+ }
+}
+
diff --git a/kioslave/media/mediamanager/mediadirnotify.h b/kioslave/media/mediamanager/mediadirnotify.h
new file mode 100644
index 000000000..beb1b8849
--- /dev/null
+++ b/kioslave/media/mediamanager/mediadirnotify.h
@@ -0,0 +1,47 @@
+/* This file is part of the KDE Project
+ Copyright (c) 2004 Kvin Ottens <ervin ipsquad net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef _MEDIADIRNOTIFY_H_
+#define _MEDIADIRNOTIFY_H_
+
+#include <kurl.h>
+#include <kdirnotify.h>
+
+#include "medialist.h"
+
+
+class MediaDirNotify : public KDirNotify
+{
+K_DCOP
+
+public:
+ MediaDirNotify(const MediaList &list);
+
+k_dcop:
+ virtual ASYNC FilesAdded (const KURL &directory);
+ virtual ASYNC FilesRemoved (const KURL::List &fileList);
+ virtual ASYNC FilesChanged (const KURL::List &fileList);
+
+private:
+ KURL::List toMediaURL(const KURL &url);
+ KURL::List toMediaURLList(const KURL::List &list);
+
+ const MediaList &m_mediaList;
+};
+
+#endif
diff --git a/kioslave/media/mediamanager/medialist.cpp b/kioslave/media/mediamanager/medialist.cpp
new file mode 100644
index 000000000..fed6091fb
--- /dev/null
+++ b/kioslave/media/mediamanager/medialist.cpp
@@ -0,0 +1,288 @@
+/* This file is part of the KDE Project
+ Copyright (c) 2004 Kévin Ottens <ervin ipsquad net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "medialist.h"
+
+#include <kdebug.h>
+
+MediaList::MediaList()
+{
+ kdDebug(1219) << "MediaList::MediaList()" << endl;
+
+ m_media.setAutoDelete(true);
+}
+
+const QPtrList<Medium> MediaList::list() const
+{
+ kdDebug(1219) << "MediaList::list()" << endl;
+
+ return m_media;
+}
+
+const Medium *MediaList::findById(const QString &id) const
+{
+ kdDebug(1219) << "MediaList::findById(" << id << ")" << endl;
+
+ if ( !m_idMap.contains(id) ) return 0L;
+
+ return m_idMap[id];
+}
+
+const Medium *MediaList::findByName(const QString &name) const
+{
+ kdDebug(1219) << "MediaList::findByName(" << name << ")" << endl;
+
+ if ( !m_nameMap.contains(name) ) return 0L;
+
+ return m_nameMap[name];
+}
+
+
+QString MediaList::addMedium(Medium *medium, bool allowNotification)
+{
+ kdDebug(1219) << "MediaList::addMedium(@" << medium->id() << ")" << endl;
+
+ QString id = medium->id();
+ if ( m_idMap.contains(id) ) return QString::null;
+
+ m_media.append( medium );
+ m_idMap[id] = medium;
+
+ QString name = medium->name();
+ if ( !m_nameMap.contains(name) )
+ {
+ m_nameMap[name] = medium;
+
+ kdDebug(1219) << "MediaList emits mediumAdded(" << id << ", "
+ << name << ")" << endl;
+ emit mediumAdded(id, name, allowNotification);
+
+ return name;
+ }
+
+ QString base_name = name+"_";
+ int i = 1;
+
+ while ( m_nameMap.contains(base_name+QString::number(i)) )
+ {
+ i++;
+ }
+
+ name = base_name+QString::number(i);
+ medium->setName(name);
+ m_nameMap[name] = medium;
+
+ kdDebug(1219) << "MediaList emits mediumAdded(" << id << ", "
+ << name << ")" << endl;
+ emit mediumAdded(id, name, allowNotification);
+ return name;
+}
+
+bool MediaList::removeMedium(const QString &id, bool allowNotification)
+{
+ kdDebug(1219) << "MediaList::removeMedium(" << id << ")" << endl;
+
+ if ( !m_idMap.contains(id) ) return false;
+
+ Medium *medium = m_idMap[id];
+ QString name = medium->name();
+
+ m_idMap.remove(id);
+ m_nameMap.remove( medium->name() );
+ m_media.remove( medium );
+
+ emit mediumRemoved(id, name, allowNotification);
+ return true;
+}
+
+bool MediaList::changeMediumState(const Medium &medium, bool allowNotification)
+{
+ kdDebug(1219) << "MediaList::changeMediumState(const Medium &)" << endl;
+
+ if ( !m_idMap.contains(medium.id()) ) return false;
+
+ Medium *m = m_idMap[medium.id()];
+
+ if ( medium.isMountable() )
+ {
+ QString device_node = medium.deviceNode();
+ QString mount_point = medium.mountPoint();
+ QString fs_type = medium.fsType();
+ bool mounted = medium.isMounted();
+
+ m->mountableState( device_node, mount_point,
+ fs_type, mounted );
+ }
+ else
+ {
+ m->unmountableState( medium.baseURL() );
+ }
+
+
+ if (!medium.mimeType().isEmpty())
+ {
+ m->setMimeType( medium.mimeType() );
+ }
+
+ if (!medium.iconName().isEmpty())
+ {
+ m->setIconName( medium.iconName() );
+ }
+
+ if (!medium.label().isEmpty())
+ {
+ m->setLabel( medium.label() );
+ }
+
+ emit mediumStateChanged(m->id(), m->name(), !m->needMounting(), allowNotification);
+ return true;
+}
+
+bool MediaList::changeMediumState(const QString &id,
+ const QString &baseURL,
+ bool allowNotification,
+ const QString &mimeType,
+ const QString &iconName,
+ const QString &label)
+{
+ kdDebug(1219) << "MediaList::changeMediumState(" << id << ", "
+ << baseURL << ", " << mimeType << ", " << iconName << ")"
+ << endl;
+
+ if ( !m_idMap.contains(id) ) return false;
+
+ Medium *medium = m_idMap[id];
+
+ medium->unmountableState( baseURL );
+
+ if (!mimeType.isEmpty())
+ {
+ medium->setMimeType( mimeType );
+ }
+
+ if (!iconName.isEmpty())
+ {
+ medium->setIconName( iconName );
+ }
+
+ if (!label.isEmpty())
+ {
+ medium->setLabel( label );
+ }
+
+ emit mediumStateChanged(id, medium->name(),
+ !medium->needMounting(),
+ allowNotification);
+ return true;
+}
+
+bool MediaList::changeMediumState(const QString &id,
+ const QString &deviceNode,
+ const QString &mountPoint,
+ const QString &fsType, bool mounted,
+ bool allowNotification,
+ const QString &mimeType,
+ const QString &iconName,
+ const QString &label)
+{
+ kdDebug(1219) << "MediaList::changeMediumState(" << id << ", "
+ << deviceNode << ", " << mountPoint << ", " << fsType << ", "
+ << mounted << ", " << mimeType << ", " << iconName << ")"
+ << endl;
+
+ if ( !m_idMap.contains(id) ) return false;
+
+ Medium *medium = m_idMap[id];
+
+ medium->mountableState( deviceNode, mountPoint, fsType, mounted );
+
+ if (!mimeType.isEmpty())
+ {
+ medium->setMimeType( mimeType );
+ }
+
+ if (!iconName.isEmpty())
+ {
+ medium->setIconName( iconName );
+ }
+
+ if (!label.isEmpty())
+ {
+ medium->setLabel( label );
+ }
+
+ emit mediumStateChanged(id, medium->name(),
+ !medium->needMounting(),
+ allowNotification);
+ return true;
+}
+
+bool MediaList::changeMediumState(const QString &id, bool mounted,
+ bool allowNotification,
+ const QString &mimeType,
+ const QString &iconName,
+ const QString &label)
+{
+ kdDebug(1219) << "MediaList::changeMediumState(" << id << ", "
+ << mounted << ", " << mimeType << ", " << iconName << ")"
+ << endl;
+
+ if ( !m_idMap.contains(id) ) return false;
+
+ Medium *medium = m_idMap[id];
+
+ if ( !medium->mountableState( mounted ) ) return false;
+
+ if (!mimeType.isEmpty())
+ {
+ medium->setMimeType( mimeType );
+ }
+
+ if (!iconName.isEmpty())
+ {
+ medium->setIconName( iconName );
+ }
+
+ if (!label.isEmpty())
+ {
+ medium->setLabel( label );
+ }
+
+ emit mediumStateChanged(id, medium->name(),
+ !medium->needMounting(),
+ allowNotification);
+ return true;
+}
+
+bool MediaList::setUserLabel(const QString &name, const QString &label)
+{
+ kdDebug(1219) << "MediaList::setUserLabel(" << name << ", "
+ << label << ")" << endl;
+
+ if ( !m_nameMap.contains(name) ) return false;
+
+ Medium *medium = m_nameMap[name];
+ medium->setUserLabel(label);
+
+ emit mediumStateChanged(medium->id(), name,
+ !medium->needMounting(),
+ false);
+ return true;
+}
+
+#include "medialist.moc"
diff --git a/kioslave/media/mediamanager/medialist.h b/kioslave/media/mediamanager/medialist.h
new file mode 100644
index 000000000..590491b0c
--- /dev/null
+++ b/kioslave/media/mediamanager/medialist.h
@@ -0,0 +1,79 @@
+/* This file is part of the KDE Project
+ Copyright (c) 2004 Kvin Ottens <ervin ipsquad net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef _MEDIALIST_H_
+#define _MEDIALIST_H_
+
+#include <qobject.h>
+
+#include "medium.h"
+
+class MediaList : public QObject
+{
+Q_OBJECT
+
+public:
+ MediaList();
+
+ // FIXME: should be <const Medium> or something similar...
+ const QPtrList<Medium> list() const;
+ const Medium *findById(const QString &id) const;
+ const Medium *findByName(const QString &name) const;
+
+public:
+ QString addMedium(Medium *medium, bool allowNotification = true);
+ bool removeMedium(const QString &id, bool allowNotification = true);
+
+ bool changeMediumState(const Medium &medium, bool allowNotification);
+ bool changeMediumState(const QString &id,
+ const QString &baseURL,
+ bool allowNotification = true,
+ const QString &mimeType = QString::null,
+ const QString &iconName = QString::null,
+ const QString &label = QString::null);
+ bool changeMediumState(const QString &id,
+ const QString &deviceNode,
+ const QString &mountPoint,
+ const QString &fsType, bool mounted,
+ bool allowNotification = true,
+ const QString &mimeType = QString::null,
+ const QString &iconName = QString::null,
+ const QString &label = QString::null);
+ bool changeMediumState(const QString &id, bool mounted,
+ bool allowNotification = true,
+ const QString &mimeType = QString::null,
+ const QString &iconName = QString::null,
+ const QString &label = QString::null);
+
+ bool setUserLabel(const QString &name, const QString &label);
+
+signals:
+ void mediumAdded(const QString &id, const QString &name,
+ bool allowNotification);
+ void mediumRemoved(const QString &id, const QString &name,
+ bool allowNotification);
+ void mediumStateChanged(const QString &id, const QString &name,
+ bool mounted, bool allowNotification);
+
+private:
+ QPtrList<Medium> m_media;
+ QMap<QString,Medium*> m_nameMap;
+ QMap<QString,Medium*> m_idMap;
+};
+
+#endif
diff --git a/kioslave/media/mediamanager/mediamanager.cpp b/kioslave/media/mediamanager/mediamanager.cpp
new file mode 100644
index 000000000..ad8f1b447
--- /dev/null
+++ b/kioslave/media/mediamanager/mediamanager.cpp
@@ -0,0 +1,342 @@
+/* This file is part of the KDE Project
+ Copyright (c) 2004 Kévin Ottens <ervin ipsquad net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "mediamanager.h"
+
+#include <config.h>
+#include <qtimer.h>
+
+#include <kdebug.h>
+#include <kglobal.h>
+#include <klocale.h>
+
+#include <kdirnotify_stub.h>
+#include <kstandarddirs.h>
+
+#include "mediamanagersettings.h"
+
+#include "fstabbackend.h"
+
+#ifdef COMPILE_HALBACKEND
+#include "halbackend.h"
+#endif //COMPILE_HALBACKEND
+
+#ifdef COMPILE_LINUXCDPOLLING
+#include "linuxcdpolling.h"
+#endif //COMPILE_LINUXCDPOLLING
+
+
+MediaManager::MediaManager(const QCString &obj)
+ : KDEDModule(obj), m_dirNotify(m_mediaList)
+{
+ connect( &m_mediaList, SIGNAL(mediumAdded(const QString&, const QString&, bool)),
+ SLOT(slotMediumAdded(const QString&, const QString&, bool)) );
+ connect( &m_mediaList, SIGNAL(mediumRemoved(const QString&, const QString&, bool)),
+ SLOT(slotMediumRemoved(const QString&, const QString&, bool)) );
+ connect( &m_mediaList,
+ SIGNAL(mediumStateChanged(const QString&, const QString&, bool, bool)),
+ SLOT(slotMediumChanged(const QString&, const QString&, bool, bool)) );
+
+ QTimer::singleShot( 10, this, SLOT( loadBackends() ) );
+}
+
+MediaManager::~MediaManager()
+{
+ while ( !m_backends.isEmpty() )
+ {
+ BackendBase *b = m_backends.first();
+ m_backends.remove( b );
+ delete b;
+ }
+}
+
+void MediaManager::loadBackends()
+{
+ m_mediaList.blockSignals(true);
+
+ while ( !m_backends.isEmpty() )
+ {
+ BackendBase *b = m_backends.first();
+ m_backends.remove( b );
+ delete b;
+ }
+
+ mp_removableBackend = 0L;
+ m_halbackend = 0L;
+ m_fstabbackend = 0L;
+
+#ifdef COMPILE_HALBACKEND
+ if ( MediaManagerSettings::self()->halBackendEnabled() )
+ {
+ m_halbackend = new HALBackend(m_mediaList, this);
+ if (m_halbackend->InitHal())
+ {
+ m_backends.append( m_halbackend );
+ m_fstabbackend = new FstabBackend(m_mediaList, true);
+ m_backends.append( m_fstabbackend );
+ // No need to load something else...
+ m_mediaList.blockSignals(false);
+ return;
+ }
+ else
+ {
+ delete m_halbackend;
+ m_halbackend = 0;
+ }
+ }
+#endif // COMPILE_HALBACKEND
+
+ mp_removableBackend = new RemovableBackend(m_mediaList);
+ m_backends.append( mp_removableBackend );
+
+#ifdef COMPILE_LINUXCDPOLLING
+ if ( MediaManagerSettings::self()->cdPollingEnabled() )
+ {
+ m_backends.append( new LinuxCDPolling(m_mediaList) );
+ }
+#endif //COMPILE_LINUXCDPOLLING
+
+ m_fstabbackend = new FstabBackend(m_mediaList);
+ m_backends.append( m_fstabbackend );
+ m_mediaList.blockSignals(false);
+}
+
+
+QStringList MediaManager::fullList()
+{
+ QPtrList<Medium> list = m_mediaList.list();
+
+ QStringList result;
+
+ QPtrList<Medium>::const_iterator it = list.begin();
+ QPtrList<Medium>::const_iterator end = list.end();
+ for (; it!=end; ++it)
+ {
+ result+= (*it)->properties();
+ result+= Medium::SEPARATOR;
+ }
+
+ return result;
+}
+
+QStringList MediaManager::properties(const QString &name)
+{
+ const Medium *m = m_mediaList.findByName(name);
+
+ if (!m)
+ {
+ KURL u(name);
+ kdDebug() << "Media::prop " << name << " " << u.isValid() << endl;
+ if (u.isValid())
+ {
+ if (u.protocol() == "system")
+ {
+ QString path = u.path();
+ if (path.startsWith("/media/"))
+ path = path.mid(strlen("/media/"));
+ m = m_mediaList.findByName(path);
+ kdDebug() << "findByName " << path << m << endl;
+ }
+ else if (u.protocol() == "media")
+ {
+ m = m_mediaList.findByName(u.filename());
+ kdDebug() << "findByName " << u.filename() << m << endl;
+ }
+ else if (u.protocol() == "file")
+ {
+ // look for the mount point
+ QPtrList<Medium> list = m_mediaList.list();
+ QPtrList<Medium>::const_iterator it = list.begin();
+ QPtrList<Medium>::const_iterator end = list.end();
+ QString path;
+
+ for (; it!=end; ++it)
+ {
+ path = KStandardDirs::realFilePath(u.path());
+ kdDebug() << "comparing " << (*it)->mountPoint() << " " << path << " " << (*it)->deviceNode() << endl;
+ if ((*it)->mountPoint() == path || (*it)->deviceNode() == path) {
+ m = *it;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (m)
+ return m->properties();
+ else
+ return QStringList();
+}
+
+QStringList MediaManager::mountoptions(const QString &name)
+{
+#ifdef COMPILE_HALBACKEND
+ if (!m_halbackend)
+ return QStringList();
+ return m_halbackend->mountoptions(name);
+#else
+ return QStringList();
+#endif
+}
+
+bool MediaManager::setMountoptions(const QString &name, const QStringList &options)
+{
+#ifdef COMPILE_HALBACKEND
+ if (!m_halbackend)
+ return false;
+ return m_halbackend->setMountoptions(name, options);
+#else
+ return false;
+#endif
+}
+
+QString MediaManager::mount(const QString &name)
+{
+#ifdef COMPILE_HALBACKEND
+ if (!m_halbackend)
+ return i18n("Feature only available with HAL");
+ return m_halbackend->mount(name);
+#else
+ if ( !m_fstabbackend ) // lying :)
+ return i18n("Feature only available with HAL");
+ return m_fstabbackend->mount( name );
+#endif
+}
+
+QString MediaManager::unmount(const QString &name)
+{
+#ifdef COMPILE_HALBACKEND
+ if (!m_halbackend)
+ return i18n("Feature only available with HAL");
+ return m_halbackend->unmount(name);
+#else
+ if ( !m_fstabbackend ) // lying :)
+ return i18n("Feature only available with HAL");
+ return m_fstabbackend->unmount( name );
+#endif
+}
+
+QString MediaManager::nameForLabel(const QString &label)
+{
+ const QPtrList<Medium> media = m_mediaList.list();
+
+ QPtrList<Medium>::const_iterator it = media.begin();
+ QPtrList<Medium>::const_iterator end = media.end();
+ for (; it!=end; ++it)
+ {
+ const Medium *m = *it;
+
+ if (m->prettyLabel()==label)
+ {
+ return m->name();
+ }
+ }
+
+ return QString::null;
+}
+
+ASYNC MediaManager::setUserLabel(const QString &name, const QString &label)
+{
+ m_mediaList.setUserLabel(name, label);
+}
+
+ASYNC MediaManager::reloadBackends()
+{
+ MediaManagerSettings::self()->readConfig();
+ loadBackends();
+}
+
+bool MediaManager::removablePlug(const QString &devNode, const QString &label)
+{
+ if (mp_removableBackend)
+ {
+ return mp_removableBackend->plug(devNode, label);
+ }
+ return false;
+}
+
+bool MediaManager::removableUnplug(const QString &devNode)
+{
+ if (mp_removableBackend)
+ {
+ return mp_removableBackend->unplug(devNode);
+ }
+ return false;
+}
+
+bool MediaManager::removableCamera(const QString &devNode)
+{
+ if (mp_removableBackend)
+ {
+ return mp_removableBackend->camera(devNode);
+ }
+ return false;
+}
+
+
+void MediaManager::slotMediumAdded(const QString &/*id*/, const QString &name,
+ bool allowNotification)
+{
+ kdDebug(1219) << "MediaManager::slotMediumAdded: " << name << endl;
+
+ KDirNotify_stub notifier("*", "*");
+ notifier.FilesAdded( KURL("media:/") );
+
+ emit mediumAdded(name, allowNotification);
+ emit mediumAdded(name);
+}
+
+void MediaManager::slotMediumRemoved(const QString &/*id*/, const QString &name,
+ bool allowNotification)
+{
+ kdDebug(1219) << "MediaManager::slotMediumRemoved: " << name << endl;
+
+ KDirNotify_stub notifier("*", "*");
+ notifier.FilesRemoved( KURL("media:/"+name) );
+
+ emit mediumRemoved(name, allowNotification);
+ emit mediumRemoved(name);
+}
+
+void MediaManager::slotMediumChanged(const QString &/*id*/, const QString &name,
+ bool mounted, bool allowNotification)
+{
+ kdDebug(1219) << "MediaManager::slotMediumChanged: " << name << endl;
+
+ KDirNotify_stub notifier("*", "*");
+ if (!mounted)
+ {
+ notifier.FilesRemoved( KURL("media:/"+name) );
+ }
+ notifier.FilesChanged( KURL("media:/"+name) );
+
+ emit mediumChanged(name, allowNotification);
+ emit mediumChanged(name);
+}
+
+
+extern "C" {
+ KDE_EXPORT KDEDModule *create_mediamanager(const QCString &obj)
+ {
+ KGlobal::locale()->insertCatalogue("kio_media");
+ return new MediaManager(obj);
+ }
+}
+
+#include "mediamanager.moc"
diff --git a/kioslave/media/mediamanager/mediamanager.desktop b/kioslave/media/mediamanager/mediamanager.desktop
new file mode 100644
index 000000000..88d8e507f
--- /dev/null
+++ b/kioslave/media/mediamanager/mediamanager.desktop
@@ -0,0 +1,141 @@
+[Desktop Entry]
+Type=Service
+Name=KDED Media Manager
+Name[af]=KDED Media Bestuurder
+Name[ar]=مسيير الوسائط KDED
+Name[az]=KDED Mediya İdarəcisi
+Name[be]=Кіраўнік носьбітаў KDED
+Name[bg]=Управление на устройствата KDED
+Name[bn]=কে.ডি.ই.ডি. মিডিয়া ম্যানেজার
+Name[bs]=KDED upravitelj medijima
+Name[ca]=Gestor de suports KDED
+Name[cs]=KDED správce médií
+Name[csb]=Menedżer zôpisownëch mediów dlô KDED
+Name[da]=KDED Mediehåndtering
+Name[de]=Medienverwaltung
+Name[el]=Διαχειριστής μέσων KDED
+Name[eo]=KDatumportila administrilo
+Name[es]=Gestor de dispositivos KDED
+Name[et]=KDED andmekandjate haldur
+Name[eu]=KDED media kudeatzailea
+Name[fa]=مدیر رسانه KDED
+Name[fi]=KDED-tallennusmedianhallinta
+Name[fr]=Gestionnaire de média KDED
+Name[fy]=KDEDED-mediabehearder
+Name[ga]=Bainisteoir Meán KDED
+Name[gl]=Xestor de Meios de KDED
+Name[he]=מנהל המדיה של KDED
+Name[hi]=केडीईडी मीडिया प्रबंधक
+Name[hr]=KDED upravitelj medija
+Name[hu]=KDED médiakezelő
+Name[is]=KDED miðilstjóri
+Name[it]=Gestore dei supporti KDED
+Name[ja]=KDED メディアマネージャ
+Name[ka]=მატარებლების მმართველი KDED
+Name[kk]=KDED ауыстырмалы тасушыларды басқару
+Name[km]=កម្មវិធី​គ្រប់គ្រង​ព័ត៌មាន KDED
+Name[ko]=KDE 창 관리자
+Name[lv]=KDED Datu nesēju menedžeris
+Name[mk]=Менаџер на носачи KDED
+Name[ms]=Pengurus Media KDED
+Name[nb]=KDED mediebehandler
+Name[nds]=KDED-Medienpleeg
+Name[ne]=KDED मिडिया प्रबन्धक
+Name[nl]=KDED-Mediabeheerder
+Name[nn]=KDED Mediehandsamar
+Name[pa]=KDED ਮਾਧਿਅਮ ਮੈਨੇਜਰ
+Name[pl]=Menedżer nośników danych dla KDED
+Name[pt]=Gestor de Dispositivos KDED
+Name[pt_BR]=Gerenciador de Mídia
+Name[ro]=Manager multimedia KDED
+Name[ru]=Управление подключаемыми устройствами
+Name[rw]=Mugenga Igihuza KDED
+Name[se]=KDED-mediagieđahalli
+Name[sk]=KDED správca médií
+Name[sl]=Upravitelj medijev KDED
+Name[sr]=Менаџер медијума, KDED
+Name[sr@Latn]=Menadžer medijuma, KDED
+Name[sv]=KDED-mediahanterare
+Name[ta]=KDED மீடியா மேலாளர்
+Name[te]=కెడిఈడి మాధ్యమ అభికర్త
+Name[th]=เครื่องมือจัดการสื่อบันทึก KDED
+Name[tr]=KDED Ortam Yöneticisi
+Name[tt]=KDED Media İdäräçe
+Name[uk]=Менеджер носіїв інформації для KDED
+Name[uz]=KDED saqlash uskunalarni boshqaruvchi
+Name[uz@cyrillic]=KDED сақлаш ускуналарни бошқарувчи
+Name[vi]=Trình quản lí Ổ lưu trữ KDED
+Name[wa]=Manaedjeu di fitchîs KDED
+Name[zh_CN]=KDED 介质管理器
+Name[zh_TW]=KDED 媒體管理程式
+Comment=Keep track of media activities and allow to (un)mount (media:/)
+Comment[af]=Hou tred van media aktiwiteite en laat die (ont)koppel van 'media:/' toe
+Comment[ar]=يتتبع نشاطات الوسائط و يسمح بتكيبها/إزالة تركيبها (media:/)
+Comment[be]=Вядзе інфармацыю аб медыяносьбітах і дазваляе прымацоўваць/адмацоўваць іх (media:/)
+Comment[bg]=Наблюдение на устройствата и разрешаване на монтиране/демонтиране на (media:/)
+Comment[bn]=কোথায় কী মিডিয়া ব্যবহার করা হচ্ছে খেয়াল রাখুন এবং (আন)মাউন্ট করুন (media:/)
+Comment[bs]=Prati aktivnosti montiranja uređaja za smještaj podataka (media:/)
+Comment[ca]=Fa el seguiment de les activitats dels suports i permet muntar i desmuntar (media:/)
+Comment[cs]=Udržuje přehled o připojených zařízeních
+Comment[csb]=Dozérô zdarzeniów sparłączonëch z mediama pòdôwków ë zezwôlô je (òd)mòntowac (media:/)
+Comment[da]=Hold styr på medieaktiviteter og tillad at (af)montere (media:/)
+Comment[de]=Überwacht Medien-Aktivität und ermöglicht das Einbinden/Lösen von Einbindungen (media:/)
+Comment[el]=Έλεγχος ενεργειών των μέσων και δυνατότητα (από)προσάρτησης (media:/)
+Comment[eo]=Sekvu spurojn de datumportilaj aktivoj kaj permesu (de/sur)meti (media:/)
+Comment[es]=Monitoriza las actividades de los recursos y permite (des)montarlos (media:/)
+Comment[et]=Hoiab silma peal andmekandjate aktiivsusel ja võimaldab neid ühendada/lahutada (media:/)
+Comment[eu]=Montatzeak begiztatzen ditu (media:/) eta desmontatzen uzten du
+Comment[fa]=حفظ رد فعالیتهای رسانه و اجازۀ سوار(پیاده) کردن (media:/)
+Comment[fi]=Pidä kirjaa tallennustapahtumista ja salli tallennusvälineen liittäminen/irrotus (devices:/)
+Comment[fr]=Gardez une trace des montages et permettre le (dé)montage (media:/)
+Comment[fy]=Hâld de media-aktiviteiten by en stien ta om media oan- en ôf te keppelje (media:/)
+Comment[gl]=Seguemento das actividades dos meios e permite-lle (des)montar (media:/)
+Comment[he]=מנטר אחר פעילויות מדיה, ומאפשר לחבר או לנתק התקנים (media:/)
+Comment[hi]=मीडिया क्रियाओं की जानकारी रखे तथा (अन)माउन्ट करने दे (मीडिया:/)
+Comment[hr]=Praćenje aktivnosti medija i omogućavanje pristupanja i napuštanja
+Comment[hu]=Az adathordozók követése, csatlakoztatása és leválasztása (media:/)
+Comment[is]=Fylgjast með breytingum á tækjum og bjóða upp á (af)tengingu (media:/)
+Comment[it]=Tiene traccia delle attività dei supporti e permette di montarli o smontarli (device:/)
+Comment[ja]=メディアの活動を追跡し、(media:/) をマウントしたりアンマウントします
+Comment[ka]=თვალყურს ადევნებს მედიის აქტიურობას და საშუალებას აძლევს (დე)მონტირების გაკეთებას (media:/)
+Comment[kk]=Тасушылардың белсендігін байқап тіркеуге не тіркеуден шығаруға мүмкіндік береді: (un)mount (media:/)
+Comment[km]=តាមដាន​សកម្មភាព​ព័ត៌មាន និង​អនុញ្ញាត​ឲ្យ​រៀបចំ (មិន​រៀបចំ) (media:/)
+Comment[lt]=Stebi laikmenose vykdomus veiksmus ir leidžia (iš)montuoti (media:/)
+Comment[lv]=Seko datu nesēju aktivitātēm un ļauj montēt/nomontēt tos (media:/)
+Comment[mk]=Води сметка за активностите на носачите и дозволува (од)монтирање (media:/)
+Comment[ms]=Ikuti perkembangan aktiviti media dan benarkan untuk (nyah)lekap (media:/)
+Comment[mt]=Żomm kont ta' attivitajiet ta' mmuntar u ippermetti (un)mount (media:/)
+Comment[nb]=Holder styr på monteringsaktiviteter og lar deg (av)montere (media:/)
+Comment[nds]=Blifft bi all Medienaktiviteten op'n Stand un verlöövt dat In- un Afhangen (media:/)
+Comment[ne]=मिडिया क्रियाकलापको मार्ग राख्नुहोस् र (अन)माउन्ट (media:/) गर्न अनुमति दिनुहोस्
+Comment[nl]=Houdt de media-activiteiten bij en staat u toe om media aan- en af te koppelen (media:/)
+Comment[nn]=Held styr på medieaktivitetar og lèt deg montera og avmontera (media:/)
+Comment[pa]=ਮਾਊਟ ਕਾਰਵਾਈਆਂ ਦੀ ਜਾਣਕਾਰੀ ਰੱਖੋ ਅਤੇ ਅਨ-ਮਾਊਟ ਕਰਨ ਦਿਓ (ਜੰਤਰ:/)
+Comment[pl]=Śledzi zdarzenia związane z nośnikami danych i pozwala je (od)montować (media:/)
+Comment[pt]=Manter o registo das actividades de dispositivos e permitir a (des)montagem (media:/)
+Comment[pt_BR]=Monitora as atividades de mídias e permite a (des)montagem (media:/)
+Comment[ro]=Urmărește activitățile multimedia și permite (de)montarea media:/
+Comment[ru]=Автоматическое подключение устройств (media:/)
+Comment[rw]=Kugumana inzira y'ibikorwa by'ibitangazamakuru no kwemerera gushyiramo(gukuramo) (ibitangazamakuru:/)
+Comment[se]=Gozit mii dáhpáhuvvá median ja diktá du gálgat ja čadnat daid (media:/)
+Comment[sk]=Sledovanie pripojenia/odpojenia medií (media:/)
+Comment[sl]=Nadzoruj dejanja medija in dovilo priklop/odklop (media:/)
+Comment[sr]=Прати активност медијума и омогућава (де)монтирање (media:/)
+Comment[sr@Latn]=Prati aktivnost medijuma i omogućava (de)montiranje (media:/)
+Comment[sv]=Håll reda på mediaaktiviteter och tillåt (av)montering (media:/)
+Comment[ta]=இடைக்காலத்திற்குரிய நடவடிக்கைகளின் வைத்திரு. (சாதனம்:/)த்தை ஏற்ற(இறக்க)கவும் அனுமதி
+Comment[th]=จะคอยติดตามกิจกรรมของสื่อบันทึก และอนุญาตให้เมานท์หรือยกเลิกการเมานท์ (media:/)
+Comment[tr]=Ortam işlemlerini takip et ve bağlanma işlemlerine izin ver(media:/)
+Comment[tt]=Cıhazlarnıñ totaşuın/ayırıluın sizüçe närsä (media:/)
+Comment[uk]=Спостерігає за змінами серед носіїв інформації та дозволяє (роз)монтування (media:/)
+Comment[vi]=Theo dõi các hoạt động của ổ lưu trữ và cho phép lắp đặt hay gỡ bỏ chúng ở thư mục "media:/"
+Comment[wa]=Wåde li trace des activités media eyet permete di (dis)monter (media:/)
+Comment[zh_CN]=跟踪介质活动并允许挂载或卸载(media:/)
+Comment[zh_TW]=持續追蹤媒體活動並允許(解除)掛載 (media:/)
+ServiceTypes=KDEDModule
+X-KDE-ModuleType=Library
+X-KDE-Library=mediamanager
+X-KDE-FactoryName=mediamanager
+X-KDE-Kded-autoload=true
+X-KDE-Kded-load-on-demand=true
+X-KDE-Kded-phase=1
diff --git a/kioslave/media/mediamanager/mediamanager.h b/kioslave/media/mediamanager/mediamanager.h
new file mode 100644
index 000000000..1e5aa1d84
--- /dev/null
+++ b/kioslave/media/mediamanager/mediamanager.h
@@ -0,0 +1,90 @@
+/* This file is part of the KDE Project
+ Copyright (c) 2004 Kvin Ottens <ervin ipsquad net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef _MEDIAMANAGER_H_
+#define _MEDIAMANAGER_H_
+
+#include <kdedmodule.h>
+#include <qstring.h>
+#include <qstringlist.h>
+
+#include "medialist.h"
+#include "backendbase.h"
+#include "removablebackend.h"
+#include "mediadirnotify.h"
+
+class HALBackend;
+class FstabBackend;
+
+class MediaManager : public KDEDModule
+{
+Q_OBJECT
+K_DCOP
+public:
+ MediaManager(const QCString &obj);
+ ~MediaManager();
+
+k_dcop:
+ QStringList fullList();
+ QStringList properties(const QString &name);
+ QStringList mountoptions(const QString &name);
+ bool setMountoptions(const QString &name, const QStringList &options);
+
+ QString mount(const QString &uid);
+ QString unmount(const QString &uid);
+
+ QString nameForLabel(const QString &label);
+ ASYNC setUserLabel(const QString &name, const QString &label);
+
+ ASYNC reloadBackends();
+
+ // Removable media handling (for people not having HAL)
+ bool removablePlug(const QString &devNode, const QString &label);
+ bool removableUnplug(const QString &devNode);
+ bool removableCamera(const QString &devNode);
+
+k_dcop_signals:
+ void mediumAdded(const QString &name, bool allowNotification);
+ void mediumRemoved(const QString &name, bool allowNotification);
+ void mediumChanged(const QString &name, bool allowNotification);
+
+ // For compatibility purpose, not needed for KDE4
+ void mediumAdded(const QString &name);
+ void mediumRemoved(const QString &name);
+ void mediumChanged(const QString &name);
+
+private slots:
+ void loadBackends();
+
+ void slotMediumAdded(const QString &id, const QString &name,
+ bool allowNotification);
+ void slotMediumRemoved(const QString &id, const QString &name,
+ bool allowNotification);
+ void slotMediumChanged(const QString &id, const QString &name,
+ bool mounted, bool allowNotification);
+
+private:
+ MediaList m_mediaList;
+ QValueList<BackendBase*> m_backends;
+ RemovableBackend *mp_removableBackend;
+ HALBackend *m_halbackend;
+ MediaDirNotify m_dirNotify;
+ FstabBackend *m_fstabbackend;
+};
+
+#endif
diff --git a/kioslave/media/mediamanager/removablebackend.cpp b/kioslave/media/mediamanager/removablebackend.cpp
new file mode 100644
index 000000000..ea8318ecf
--- /dev/null
+++ b/kioslave/media/mediamanager/removablebackend.cpp
@@ -0,0 +1,180 @@
+/* This file is part of the KDE Project
+ Copyright (c) 2004 Kévin Ottens <ervin ipsquad net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "removablebackend.h"
+
+#include <klocale.h>
+#include <kdirwatch.h>
+#include <kurl.h>
+#include <kmountpoint.h>
+#include <kstandarddirs.h>
+
+#ifdef _OS_SOLARIS_
+#define MTAB "/etc/mnttab"
+#else
+#define MTAB "/etc/mtab"
+#endif
+
+
+
+RemovableBackend::RemovableBackend(MediaList &list)
+ : QObject(), BackendBase(list)
+{
+ KDirWatch::self()->addFile(MTAB);
+
+ connect( KDirWatch::self(), SIGNAL( dirty(const QString&) ),
+ this, SLOT( slotDirty(const QString&) ) );
+ KDirWatch::self()->startScan();
+}
+
+RemovableBackend::~RemovableBackend()
+{
+ QStringList::iterator it = m_removableIds.begin();
+ QStringList::iterator end = m_removableIds.end();
+
+ for (; it!=end; ++it)
+ {
+ m_mediaList.removeMedium(*it, false);
+ }
+
+ KDirWatch::self()->removeFile(MTAB);
+}
+
+bool RemovableBackend::plug(const QString &devNode, const QString &label)
+{
+ QString name = generateName(devNode);
+ QString id = generateId(devNode);
+
+ if (!m_removableIds.contains(id))
+ {
+ Medium *medium = new Medium(id, name);
+ medium->mountableState(devNode, QString::null,
+ QString::null, false);
+
+ QStringList words = QStringList::split(" ", label);
+
+ QStringList::iterator it = words.begin();
+ QStringList::iterator end = words.end();
+
+ QString tmp = (*it).lower();
+ tmp[0] = tmp[0].upper();
+ QString new_label = tmp;
+
+ ++it;
+ for (; it!=end; ++it)
+ {
+ tmp = (*it).lower();
+ tmp[0] = tmp[0].upper();
+ new_label+= " "+tmp;
+ }
+
+ medium->setLabel(new_label);
+ medium->setMimeType("media/removable_unmounted");
+
+ m_removableIds.append(id);
+ return !m_mediaList.addMedium(medium).isNull();
+ }
+ return false;
+}
+
+bool RemovableBackend::unplug(const QString &devNode)
+{
+ QString id = generateId(devNode);
+ if (m_removableIds.contains(id))
+ {
+ m_removableIds.remove(id);
+ return m_mediaList.removeMedium(id);
+ }
+ return false;
+}
+
+bool RemovableBackend::camera(const QString &devNode)
+{
+ QString id = generateId(devNode);
+ if (m_removableIds.contains(id))
+ {
+ return m_mediaList.changeMediumState(id,
+ QString("camera:/"), false, "media/gphoto2camera");
+ }
+ return false;
+}
+
+void RemovableBackend::slotDirty(const QString &path)
+{
+ if (path==MTAB)
+ {
+ handleMtabChange();
+ }
+}
+
+
+void RemovableBackend::handleMtabChange()
+{
+ QStringList new_mtabIds;
+ KMountPoint::List mtab = KMountPoint::currentMountPoints();
+
+ KMountPoint::List::iterator it = mtab.begin();
+ KMountPoint::List::iterator end = mtab.end();
+
+ for (; it!=end; ++it)
+ {
+ QString dev = (*it)->mountedFrom();
+ QString mp = (*it)->mountPoint();
+ QString fs = (*it)->mountType();
+
+ QString id = generateId(dev);
+ new_mtabIds+=id;
+
+ if ( !m_mtabIds.contains(id)
+ && m_removableIds.contains(id) )
+ {
+ m_mediaList.changeMediumState(id, dev, mp, fs, true,
+ false, "media/removable_mounted");
+ }
+ }
+
+ QStringList::iterator it2 = m_mtabIds.begin();
+ QStringList::iterator end2 = m_mtabIds.end();
+
+ for (; it2!=end2; ++it2)
+ {
+ if ( !new_mtabIds.contains(*it2)
+ && m_removableIds.contains(*it2) )
+ {
+ m_mediaList.changeMediumState(*it2, false,
+ false, "media/removable_unmounted");
+ }
+ }
+
+ m_mtabIds = new_mtabIds;
+}
+
+QString RemovableBackend::generateId(const QString &devNode)
+{
+ QString dev = KStandardDirs::realFilePath(devNode);
+
+ return "/org/kde/mediamanager/removable/"
+ +dev.replace("/", "");
+}
+
+QString RemovableBackend::generateName(const QString &devNode)
+{
+ return KURL(devNode).fileName();
+}
+
+#include "removablebackend.moc"
diff --git a/kioslave/media/mediamanager/removablebackend.h b/kioslave/media/mediamanager/removablebackend.h
new file mode 100644
index 000000000..02fc0409e
--- /dev/null
+++ b/kioslave/media/mediamanager/removablebackend.h
@@ -0,0 +1,52 @@
+/* This file is part of the KDE Project
+ Copyright (c) 2004 Kvin Ottens <ervin ipsquad net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef _REMOVABLEBACKEND_H_
+#define _REMOVABLEBACKEND_H_
+
+#include "backendbase.h"
+
+#include <qobject.h>
+#include <qstringlist.h>
+
+class RemovableBackend : public QObject, public BackendBase
+{
+Q_OBJECT
+
+public:
+ RemovableBackend(MediaList &list);
+ virtual ~RemovableBackend();
+
+ bool plug(const QString &devNode, const QString &label);
+ bool unplug(const QString &devNode);
+ bool camera(const QString &devNode);
+
+private slots:
+ void slotDirty(const QString &path);
+
+private:
+ void handleMtabChange();
+
+ static QString generateId(const QString &devNode);
+ static QString generateName(const QString &devNode);
+
+ QStringList m_removableIds;
+ QStringList m_mtabIds;
+};
+
+#endif
diff --git a/kioslave/media/medianotifier/Makefile.am b/kioslave/media/medianotifier/Makefile.am
new file mode 100644
index 000000000..a0bff573e
--- /dev/null
+++ b/kioslave/media/medianotifier/Makefile.am
@@ -0,0 +1,18 @@
+INCLUDES = -I$(srcdir)/../libmediacommon -I../libmediacommon $(all_includes)
+
+kde_module_LTLIBRARIES = kded_medianotifier.la
+kded_medianotifier_la_LDFLAGS = -module -avoid-version $(all_libraries)
+kded_medianotifier_la_LIBADD = ../libmediacommon/libmediacommon.la $(LIB_KDECORE) \
+ $(LIB_KDEUI) $(LIB_KIO)
+kded_medianotifier_la_SOURCES = medianotifier.cpp medianotifier.skel \
+ notificationdialog.cpp notificationdialogview.ui
+
+noinst_HEADERS = medianotifier.h notificationdialog.h
+
+METASOURCES = AUTO
+
+services_DATA = medianotifier.desktop
+servicesdir = $(kde_servicesdir)/kded
+
+messages: rc.cpp
+ $(XGETTEXT) *.cpp -o $(podir)/kay.pot
diff --git a/kioslave/media/medianotifier/medianotifier.cpp b/kioslave/media/medianotifier/medianotifier.cpp
new file mode 100644
index 000000000..98a474ba7
--- /dev/null
+++ b/kioslave/media/medianotifier/medianotifier.cpp
@@ -0,0 +1,312 @@
+/* This file is part of the KDE Project
+ Copyright (c) 2005 Jean-Remy Falleri <jr.falleri@laposte.net>
+ Copyright (c) 2005 Kévin Ottens <ervin ipsquad net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "medianotifier.h"
+
+#include <qfile.h>
+#include <qfileinfo.h>
+
+#include <kapplication.h>
+#include <kglobal.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <kprocess.h>
+#include <krun.h>
+#include <kmessagebox.h>
+#include <kstdguiitem.h>
+#include <kstandarddirs.h>
+
+#include "notificationdialog.h"
+#include "notifiersettings.h"
+#include "notifieraction.h"
+#include "mediamanagersettings.h"
+
+MediaNotifier::MediaNotifier(const QCString &name) : KDEDModule(name)
+{
+ connectDCOPSignal( "kded", "mediamanager", "mediumAdded(QString, bool)",
+ "onMediumChange(QString, bool)", true );
+
+ connectDCOPSignal( "kded", "mediamanager", "mediumChanged(QString, bool)",
+ "onMediumChange(QString, bool)", true );
+}
+
+MediaNotifier::~MediaNotifier()
+{
+ disconnectDCOPSignal( "kded", "mediamanager", "mediumAdded(QString, bool)",
+ "onMediumChange(QString, bool)" );
+
+ disconnectDCOPSignal( "kded", "mediamanager", "mediumChanged(QString, bool)",
+ "onMediumChange(QString, bool)" );
+}
+
+void MediaNotifier::onMediumChange( const QString &name, bool allowNotification )
+{
+ kdDebug() << "MediaNotifier::onMediumChange( " << name << ", "
+ << allowNotification << ")" << endl;
+
+ if ( !allowNotification )
+ return;
+
+// Update user activity timestamp, otherwise the notification dialog will be shown
+// in the background due to focus stealing prevention. Entering a new media can
+// be seen as a kind of user activity after all. It'd be better to update the timestamp
+// as soon as the media is entered, but it apparently takes some time to get here.
+ kapp->updateUserTimestamp();
+
+ KURL url( "system:/media/"+name );
+
+ KIO::SimpleJob *job = KIO::stat( url, false );
+ job->setInteractive( false );
+
+ m_allowNotificationMap[job] = allowNotification;
+
+ connect( job, SIGNAL( result( KIO::Job * ) ),
+ this, SLOT( slotStatResult( KIO::Job * ) ) );
+}
+
+void MediaNotifier::slotStatResult( KIO::Job *job )
+{
+ bool allowNotification = m_allowNotificationMap[job];
+ m_allowNotificationMap.remove( job );
+
+ if ( job->error() != 0 ) return;
+
+ KIO::StatJob *stat_job = static_cast<KIO::StatJob *>( job );
+
+ KIO::UDSEntry entry = stat_job->statResult();
+ KURL url = stat_job->url();
+
+ KFileItem medium( entry, url );
+
+ if ( autostart( medium ) ) return;
+
+ if ( allowNotification ) notify( medium );
+}
+
+bool MediaNotifier::autostart( const KFileItem &medium )
+{
+ QString mimetype = medium.mimetype();
+
+ bool is_cdrom = mimetype.startsWith( "cd" ) || mimetype.startsWith( "dvd" );
+ bool is_mounted = mimetype.endsWith( "_mounted" );
+
+ // We autorun only on CD/DVD or removable disks (USB, Firewire)
+ if ( !( is_cdrom || is_mounted )
+ && mimetype!="media/removable_mounted" )
+ {
+ return false;
+ }
+
+
+ // Here starts the 'Autostart Of Applications After Mount' implementation
+
+ // The desktop environment MAY ignore Autostart files altogether
+ // based on policy set by the user, system administrator or vendor.
+ MediaManagerSettings::self()->readConfig();
+ if ( !MediaManagerSettings::self()->autostartEnabled() )
+ {
+ return false;
+ }
+
+ // From now we're sure the medium is already mounted.
+ // We can use the local path for stating, no need to use KIO here.
+ bool local;
+ QString path = medium.mostLocalURL( local ).path(); // local is always true here...
+
+ // When a new medium is mounted the root directory of the medium should
+ // be checked for the following Autostart files in order of precedence:
+ // .autorun, autorun, autorun.sh
+ QStringList autorun_list;
+ autorun_list << ".autorun" << "autorun" << "autorun.sh";
+
+ QStringList::iterator it = autorun_list.begin();
+ QStringList::iterator end = autorun_list.end();
+
+ for ( ; it!=end; ++it )
+ {
+ if ( QFile::exists( path + "/" + *it ) )
+ {
+ return execAutorun( medium, path, *it );
+ }
+ }
+
+ // When a new medium is mounted the root directory of the medium should
+ // be checked for the following Autoopen files in order of precedence:
+ // .autoopen, autoopen
+ QStringList autoopen_list;
+ autoopen_list << ".autoopen" << "autoopen";
+
+ it = autoopen_list.begin();
+ end = autoopen_list.end();
+
+ for ( ; it!=end; ++it )
+ {
+ if ( QFile::exists( path + "/" + *it ) )
+ {
+ return execAutoopen( medium, path, *it );
+ }
+ }
+
+ return false;
+}
+
+bool MediaNotifier::execAutorun( const KFileItem &medium, const QString &path,
+ const QString &autorunFile )
+{
+ // The desktop environment MUST prompt the user for confirmation
+ // before automatically starting an application.
+ QString mediumType = medium.mimeTypePtr()->name();
+ QString text = i18n( "An autorun file has been found on your '%1'."
+ " Do you want to execute it?\n"
+ "Note that executing a file on a medium may compromise"
+ " your system's security").arg( mediumType );
+ QString caption = i18n( "Autorun - %1" ).arg( medium.url().prettyURL() );
+ KGuiItem yes = KStdGuiItem::yes();
+ KGuiItem no = KStdGuiItem::no();
+ int options = KMessageBox::Notify | KMessageBox::Dangerous;
+
+ int answer = KMessageBox::warningYesNo( 0L, text, caption, yes, no,
+ QString::null, options );
+
+ if ( answer == KMessageBox::Yes )
+ {
+ // When an Autostart file has been detected and the user has
+ // confirmed its execution the autostart file MUST be executed
+ // with the current working directory ( CWD ) set to the root
+ // directory of the medium.
+ KProcess proc;
+ proc << "sh" << autorunFile;
+ proc.setWorkingDirectory( path );
+ proc.start();
+ proc.detach();
+ }
+
+ return true;
+}
+
+bool MediaNotifier::execAutoopen( const KFileItem &medium, const QString &path,
+ const QString &autoopenFile )
+{
+ // An Autoopen file MUST contain a single relative path that points
+ // to a non-executable file contained on the medium. [...]
+ QFile file( path+"/"+autoopenFile );
+ file.open( IO_ReadOnly );
+ QTextStream stream( &file );
+
+ QString relative_path = stream.readLine().stripWhiteSpace();
+
+ // The relative path MUST NOT contain path components that
+ // refer to a parent directory ( ../ )
+ if ( relative_path.startsWith( "/" ) || relative_path.contains( "../" ) )
+ {
+ return false;
+ }
+
+ // The desktop environment MUST verify that the relative path points
+ // to a file that is actually located on the medium [...]
+ QString resolved_path
+ = KStandardDirs::realFilePath( path+"/"+relative_path );
+
+ if ( !resolved_path.startsWith( path ) )
+ {
+ return false;
+ }
+
+
+ QFile document( resolved_path );
+
+ // TODO: What about FAT all files are executable...
+ // If the relative path points to an executable file then the desktop
+ // environment MUST NOT execute the file.
+ if ( !document.exists() /*|| QFileInfo(document).isExecutable()*/ )
+ {
+ return false;
+ }
+
+ KURL url = medium.url();
+ url.addPath( relative_path );
+
+ // The desktop environment MUST prompt the user for confirmation
+ // before opening the file.
+ QString mediumType = medium.mimeTypePtr()->name();
+ QString filename = url.filename();
+ QString text = i18n( "An autoopen file has been found on your '%1'."
+ " Do you want to open '%2'?\n"
+ "Note that opening a file on a medium may compromise"
+ " your system's security").arg( mediumType ).arg( filename );
+ QString caption = i18n( "Autoopen - %1" ).arg( medium.url().prettyURL() );
+ KGuiItem yes = KStdGuiItem::yes();
+ KGuiItem no = KStdGuiItem::no();
+ int options = KMessageBox::Notify | KMessageBox::Dangerous;
+
+ int answer = KMessageBox::warningYesNo( 0L, text, caption, yes, no,
+ QString::null, options );
+
+ // TODO: Take case of the "UNLESS" part?
+ // When an Autoopen file has been detected and the user has confirmed
+ // that the file indicated in the Autoopen file should be opened then
+ // the file indicated in the Autoopen file MUST be opened in the
+ // application normally preferred by the user for files of its kind
+ // UNLESS the user instructed otherwise.
+ if ( answer == KMessageBox::Yes )
+ {
+ ( void ) new KRun( url );
+ }
+
+ return true;
+}
+
+void MediaNotifier::notify( KFileItem &medium )
+{
+ kdDebug() << "Notification triggered." << endl;
+
+ NotifierSettings *settings = new NotifierSettings();
+
+ if ( settings->autoActionForMimetype( medium.mimetype() )==0L )
+ {
+ QValueList<NotifierAction*> actions
+ = settings->actionsForMimetype( medium.mimetype() );
+
+ // If only one action remains, it's the "do nothing" action
+ // no need to popup in this case.
+ if ( actions.size()>1 )
+ {
+ NotificationDialog *dialog
+ = new NotificationDialog( medium, settings );
+ dialog->show();
+ }
+ }
+ else
+ {
+ NotifierAction *action = settings->autoActionForMimetype( medium.mimetype() );
+ action->execute( medium );
+ delete settings;
+ }
+}
+
+extern "C"
+{
+ KDE_EXPORT KDEDModule *create_medianotifier(const QCString &name)
+ {
+ KGlobal::locale()->insertCatalogue("kay");
+ return new MediaNotifier(name);
+ }
+}
+
+#include "medianotifier.moc"
diff --git a/kioslave/media/medianotifier/medianotifier.desktop b/kioslave/media/medianotifier/medianotifier.desktop
new file mode 100644
index 000000000..1bd0a2be1
--- /dev/null
+++ b/kioslave/media/medianotifier/medianotifier.desktop
@@ -0,0 +1,122 @@
+[Desktop Entry]
+Type=Service
+ServiceTypes=KDEDModule
+X-KDE-ModuleType=Library
+X-KDE-Library=medianotifier
+X-KDE-FactoryName=medianotifier
+X-KDE-Kded-autoload=true
+X-KDE-Kded-load-on-demand=false
+Name=Media Notifier Daemon
+Name[af]=Media Inkennistelling Bediener
+Name[ar]=مراقبالتبليغ عن وسائط
+Name[be]=Дэман нагадванняў аб носьбітах
+Name[bg]=Мултимедиен демон
+Name[bn]=মিডিয়া বিজ্ঞপ্তি ডিমন
+Name[bs]=Daemon za obavještenja o novim medijima
+Name[ca]=Dimoni notificador de suports
+Name[cs]=Démon upozorňování na média
+Name[csb]=Ùsłëżnota pòwiadomieniô ò zôpisownëch mediach
+Name[da]=Mediebekendtgørelsesdæmon
+Name[de]=Geräteüberwachung
+Name[el]=Δαίμονας ειδοποίησης μέσων
+Name[eo]=Media-atentigilo
+Name[es]=Demonio de notificaciones de medios
+Name[et]=Andmekandjate märguannete deemon
+Name[eu]=Euskarrien jakinarazpen daemon-a
+Name[fa]=شبح اخطاردهندۀ رسانه
+Name[fi]=Mediahuomautin
+Name[fr]=Démon de notifications des média
+Name[fy]=Medianotifikaasje-daemon
+Name[gl]=Demo de Notificacións dos Médios
+Name[he]=שירות הודעות מערכת
+Name[hr]=Demon obavijesti o medijima
+Name[hu]=Lemezfigyelő szolgáltatás
+Name[is]=Miðils tilkynningarpúki
+Name[it]=Demone notifiche dispositivi
+Name[ja]=メディア通知デーモン
+Name[ka]=მედიის შემტყობინებელი
+Name[kk]=Медиа туралы құлақтандыру қызметі
+Name[km]=ដេមិន​របស់​ឧបករណ៍​ប្រាប់​ដំណឹង​មេឌៀ
+Name[lt]=Media pranešimų tarnyba
+Name[nb]=Medievarslingsnisse
+Name[nds]=Medien-Narichtendämoon
+Name[ne]=मिडिया सूचक डेइमन
+Name[nl]=Medianotificatie-daemon
+Name[nn]=Mediepåminningsnisse
+Name[pa]=ਮੀਡਿਆ ਸੂਚਨਾ ਡੈਮਨ
+Name[pl]=Usługa powiadamiania o nośnikach
+Name[pt]=Servidor de Notificação de Dispositivos
+Name[pt_BR]=Daemon de Notificação de Mídia
+Name[ro]=Daemonul de notificare mediu
+Name[ru]=Демон уведомлений от подключаемых устройств
+Name[sk]=Notifikátor medií
+Name[sl]=Demon za obveščanje o nosilcih
+Name[sr]=Демон за обавештења о медијумима
+Name[sr@Latn]=Demon za obaveštenja o medijumima
+Name[sv]=Demon för mediaunderrättelser
+Name[th]=เดมอนแจ้งเตือนสำหรับสื่อบันทึก
+Name[tr]=CD/USB/Firewire Durum İzleme Sistemi
+Name[uk]=Демон сповіщення про носії інформації
+Name[uz]=Saqlash uskunalar uchun demon
+Name[uz@cyrillic]=Сақлаш ускуналар учун демон
+Name[vi]=Trình nền Thông báo Ổ lưu trữ
+Name[wa]=Demon di notifiaedje media
+Name[zh_CN]=介质通知守护程序
+Name[zh_TW]=媒體通知伺服程式
+Comment=A media plugged notifier
+Comment[af]='n Inpropbare media inkennissteller
+Comment[ar]=مبلِغ عن إدخال وسائط
+Comment[be]=Дэман нагадванняў аб зменах стану носьбітаў
+Comment[bg]=Мултимедиен демон за уведомяване при поставяне/включване на ново мултимедийно устройство
+Comment[bn]=নতুন মিডিয়া প্রবেশ করলে তা জানায়
+Comment[bs]=Obavještenje da je novi uređaj priključen
+Comment[ca]=Un notificador de què s'ha introduït un suport
+Comment[cs]=Upozorňování na připojená média
+Comment[csb]=Wiédzô ò przëłączeniô zôpisownëch mediów
+Comment[da]=En opdager af at medier sættes ind
+Comment[de]=Benachrichtigt das System über angeschlossene Geräte
+Comment[el]=Ένας ειδοποιητής εισαγωγής μέσου
+Comment[eo]=Media konekt-atentigilo
+Comment[es]=Un notificador de medios empotrable
+Comment[et]=Andmekandja ühendamisest märkuandev deemon
+Comment[eu]=Euskarri konektatze jakinarazlea
+Comment[fa]=یک اخطاردهندۀ وصل‌شدۀ رسانه
+Comment[fi]=Liitetyn median huomautin
+Comment[fr]=Notification de connexion de média
+Comment[fy]=Meidieling fan oankeppele media
+Comment[gl]=Un notificador de meios disponíbeis
+Comment[hr]=Priključeno obavještavanje o medijima
+Comment[hu]=Lemezérzékelő
+Comment[is]=Tilkynnari um tengda miðla
+Comment[it]=Notifiche dei dispositivi attaccati
+Comment[ja]=メディアの接続を通知します
+Comment[ka]=მედიის ჩადგმის შემტყობინებელი
+Comment[kk]=Медиа салынған туралы құлақтандыру
+Comment[lt]=Perspėjimo apie media prijungimą priedas
+Comment[mk]=Известување за приклучен медиум
+Comment[nb]=En medievarsler som programtillegg
+Comment[nds]=En Deenst för Narichten över tokoppelt Reedschappen
+Comment[ne]=मिडिया प्लग गरिएको सूचक
+Comment[nl]=Meldingen van aangesloten media
+Comment[nn]=Ein medievarslar som programtillegg
+Comment[pa]=ਇੱਕ ਮੀਡਿਆ ਪਲੱਗ ਸੂਚਕ
+Comment[pl]=Powiadamianie o podłączeniu nośników danych
+Comment[pt]=Um notificador ligado aos dispositivos
+Comment[pt_BR]=um notificador para mídia que é espetada (plug)
+Comment[ro]=Un notificator de adăugare mediu
+Comment[ru]=Система обработки уведомлений от подключаемых устройств
+Comment[sk]=Notifikátor pripojených médií
+Comment[sl]=Obveščanje o vstavljenih/priklopljenih nosilcih
+Comment[sr]=Обавештавач о укљученим медијима
+Comment[sr@Latn]=Obaveštavač o uključenim medijima
+Comment[sv]=Inbäddad mediaunderrättelse
+Comment[th]=ตัวแจ้งเตือนการเสียบสื่อบันทึก
+Comment[tr]=CD/USB/Firewire durum izleme sistemi
+Comment[tt]=Cıhaz totaşılğan buluı turında beldergeç
+Comment[uk]=Сповіщення про приєднання носіїв інформації
+Comment[uz]=Saqlash uskunalar ulanganida xabar beruvchi
+Comment[uz@cyrillic]=Сақлаш ускуналар уланганида хабар берувчи
+Comment[vi]=Trình thông báo về các ổ lưu trữ đã kết nối
+Comment[wa]=Notifiaedje di medias tchôké dvins
+Comment[zh_CN]=介质插入通知器
+Comment[zh_TW]=媒體插入通知程式
diff --git a/kioslave/media/medianotifier/medianotifier.h b/kioslave/media/medianotifier/medianotifier.h
new file mode 100644
index 000000000..c3e4b9bf9
--- /dev/null
+++ b/kioslave/media/medianotifier/medianotifier.h
@@ -0,0 +1,57 @@
+/* This file is part of the KDE Project
+ Copyright (c) 2005 Jean-Remy Falleri <jr.falleri@laposte.net>
+ Copyright (c) 2005 Kvin Ottens <ervin ipsquad net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef _MEDIANOTIFIER_H_
+#define _MEDIANOTIFIER_H_
+
+#include <kdedmodule.h>
+#include <kfileitem.h>
+#include <kio/job.h>
+
+#include <qstring.h>
+#include <qmap.h>
+
+class MediaNotifier: public KDEDModule
+{
+ Q_OBJECT
+ K_DCOP
+
+public:
+ MediaNotifier( const QCString &name );
+ virtual ~MediaNotifier();
+
+k_dcop:
+ void onMediumChange( const QString &name, bool allowNotification );
+
+private slots:
+ void slotStatResult( KIO::Job *job );
+
+private:
+ bool autostart( const KFileItem &medium );
+ void notify( KFileItem &medium );
+
+ bool execAutorun( const KFileItem &medium, const QString &path,
+ const QString &autorunFile );
+ bool execAutoopen( const KFileItem &medium, const QString &path,
+ const QString &autoopenFile );
+
+ QMap<KIO::Job*,bool> m_allowNotificationMap;
+};
+#endif
+
diff --git a/kioslave/media/medianotifier/notificationdialog.cpp b/kioslave/media/medianotifier/notificationdialog.cpp
new file mode 100644
index 000000000..a4dab0245
--- /dev/null
+++ b/kioslave/media/medianotifier/notificationdialog.cpp
@@ -0,0 +1,147 @@
+/* This file is part of the KDE Project
+ Copyright (c) 2005 Jean-Remy Falleri <jr.falleri@laposte.net>
+ Copyright (c) 2005 Kévin Ottens <ervin ipsquad net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "notificationdialog.h"
+#include <qlayout.h>
+
+#include <krun.h>
+#include <klocale.h>
+#include <kstandarddirs.h>
+#include <kio/global.h>
+#include <klistbox.h>
+#include <qlabel.h>
+#include <qcheckbox.h>
+#include <qpushbutton.h>
+
+#include "actionlistboxitem.h"
+#include "notificationdialogview.h"
+
+NotificationDialog::NotificationDialog( KFileItem medium, NotifierSettings *settings,
+ QWidget* parent, const char* name )
+ : KDialogBase( parent, name, false, i18n( "Medium Detected" ), Ok|Cancel|User1, Ok, true),
+ m_medium(medium), m_settings( settings )
+{
+ setCaption( KIO::decodeFileName(m_medium.name()) );
+ clearWState( WState_Polished );
+
+ QWidget *page = new QWidget( this );
+ setMainWidget(page);
+ QVBoxLayout *topLayout = new QVBoxLayout( page, 0, spacingHint() );
+
+ m_view = new NotificationDialogView( page );
+
+ topLayout->addWidget(m_view);
+ m_view->iconLabel->setPixmap( m_medium.pixmap(64) );
+ m_view->mimetypeLabel->setText( i18n( "<b>Medium type:</b>" ) + " "
+ + m_medium.mimeTypePtr()->comment() );
+
+ updateActionsListBox();
+
+ resize( QSize(400,400).expandedTo( minimumSizeHint() ) );
+
+
+ m_actionWatcher = new KDirWatch();
+ QString services_dir
+ = locateLocal( "data", "konqueror/servicemenus", true );
+ m_actionWatcher->addDir( services_dir );
+
+ setButtonText( User1, i18n("Configure...") );
+
+ connect( m_actionWatcher, SIGNAL( dirty( const QString & ) ),
+ this, SLOT( slotActionsChanged( const QString & ) ) );
+ connect( this , SIGNAL( okClicked() ),
+ this, SLOT( slotOk() ) );
+ connect( this, SIGNAL( user1Clicked() ),
+ this, SLOT( slotConfigure() ) );
+ connect( m_view->actionsList, SIGNAL( doubleClicked ( QListBoxItem*, const QPoint & ) ),
+ this, SLOT( slotOk() ) );
+
+ connect( this, SIGNAL( finished() ),
+ this, SLOT( delayedDestruct() ) );
+
+ m_actionWatcher->startScan();
+ QPushButton * btn = actionButton( Ok );
+ btn->setFocus();
+}
+
+NotificationDialog::~NotificationDialog()
+{
+ delete m_actionWatcher;
+ delete m_settings;
+}
+
+void NotificationDialog::updateActionsListBox()
+{
+ m_view->actionsList->clear();
+
+ QValueList<NotifierAction*> actions
+ = m_settings->actionsForMimetype( m_medium.mimetype() );
+
+ QValueList<NotifierAction*>::iterator it = actions.begin();
+ QValueList<NotifierAction*>::iterator end = actions.end();
+
+ for ( ; it!=end; ++it )
+ {
+ new ActionListBoxItem( *it, m_medium.mimetype(),
+ m_view->actionsList );
+ }
+
+ m_view->actionsList->setSelected( 0, true );
+}
+
+
+void NotificationDialog::slotActionsChanged(const QString &/*dir*/)
+{
+ m_settings->reload();
+ updateActionsListBox();
+}
+
+void NotificationDialog::slotOk()
+{
+ QListBoxItem *item = m_view->actionsList->selectedItem();
+
+ if ( item != 0L )
+ {
+ ActionListBoxItem *action_item
+ = static_cast<ActionListBoxItem*>( item );
+ NotifierAction *action = action_item->action();
+
+ launchAction( action );
+ }
+}
+
+void NotificationDialog::launchAction( NotifierAction *action )
+{
+ if ( m_view->autoActionCheck->isChecked() )
+ {
+ m_settings->setAutoAction( m_medium.mimetype(), action );
+ m_settings->save();
+ }
+
+ action->execute(m_medium);
+
+ QDialog::accept();
+}
+
+void NotificationDialog::slotConfigure()
+{
+ KRun::runCommand("kcmshell media");
+}
+
+#include "notificationdialog.moc"
diff --git a/kioslave/media/medianotifier/notificationdialog.h b/kioslave/media/medianotifier/notificationdialog.h
new file mode 100644
index 000000000..94db1fee0
--- /dev/null
+++ b/kioslave/media/medianotifier/notificationdialog.h
@@ -0,0 +1,56 @@
+/* This file is part of the KDE Project
+ Copyright (c) 2005 Jean-Remy Falleri <jr.falleri@laposte.net>
+ Copyright (c) 2005 Kvin Ottens <ervin ipsquad net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef _NOTIFICATIONDIALOG_H_
+#define _NOTIFICATIONDIALOG_H_
+
+#include <kdialogbase.h>
+#include <klistbox.h>
+#include <kdirwatch.h>
+#include <kfileitem.h>
+
+#include "notifiersettings.h"
+#include "notifieraction.h"
+#include "notificationdialogview.h"
+
+class NotificationDialog : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+ NotificationDialog( KFileItem medium, NotifierSettings *settings,
+ QWidget* parent = 0, const char* name = 0 );
+ ~NotificationDialog();
+
+private slots:
+ void slotOk();
+ void slotConfigure();
+ void slotActionsChanged(const QString& dir);
+
+private:
+ void launchAction( NotifierAction *action );
+ void updateActionsListBox();
+
+ KFileItem m_medium;
+ NotifierSettings *m_settings;
+ KDirWatch * m_actionWatcher;
+ NotificationDialogView *m_view;
+};
+
+#endif
diff --git a/kioslave/media/medianotifier/notificationdialogview.ui b/kioslave/media/medianotifier/notificationdialogview.ui
new file mode 100644
index 000000000..f37a007b2
--- /dev/null
+++ b/kioslave/media/medianotifier/notificationdialogview.ui
@@ -0,0 +1,117 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>NotificationDialogView</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>NotificationDialogView</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>508</width>
+ <height>480</height>
+ </rect>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="spacing">
+ <number>15</number>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout2</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="spacing">
+ <number>20</number>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>iconLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>64</width>
+ <height>64</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>64</width>
+ <height>64</height>
+ </size>
+ </property>
+ <property name="pixmap">
+ <pixmap>image0</pixmap>
+ </property>
+ <property name="scaledContents">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>A new medium has been detected.&lt;br&gt;&lt;b&gt;What do you want to do?&lt;/b&gt;</string>
+ </property>
+ <property name="textFormat">
+ <enum>RichText</enum>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>mimetypeLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>...</string>
+ </property>
+ </widget>
+ <widget class="KListBox">
+ <property name="name">
+ <cstring>actionsList</cstring>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>autoActionCheck</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Always do this for this type of media</string>
+ </property>
+ </widget>
+ </vbox>
+</widget>
+<images>
+ <image name="image0">
+ <data format="XPM.GZ" length="55092">789cccbd47b7eb38b2ef397f9fa2d6e5ecae5e7cf266d0035266cb6da7ed77af1ed07b2f1aa9bf7c83883f704c56d5cd7c75bb5f95d6c9ca5f8a22114044202200f0fccffffcdbe7d3fddffef37ffe8fea625c02eb6f966f947ffb4fbb4e92ebfff57fff9fffcffff88fe160f0b7fecf68389bfe6df41fffc7fff80febf96fd6df9401ff5fcff64232ffde36244f7a762ac953fefd56f29cf35cf2a267f3072ff9f733c906e7836493f35eb2c59fd74ab6797b1f243bfcfb46b2cb7fef0a1e72799c5af2907f7f94cce5732cc963fefd483297cf3a8387d43f992999ffde0c25f3dfb79a64de5f662099dfcfe924cf386f24f3fe4a44ff0fd17e5b327f9e772799dfcfb8078fa87d662499cbebbb9249de6fc9bcbd9d2f99dab795ccc7b31a48e6e3b71a4ae6e315ed25f3f1b04f82a93f0dc1636a9ff32999daf32599f757a54ae6fde17e48e6fae23892b97e78a2bd63ea1f438cef849e97e892f9f7652b99b76f3d91cce53763f0947e6f08fd9c1137b664de5e43c83fc7f53bf0022cf475499c8be719c4f113d824de5cc01671fd0eb6895dbaff50d8ab174ae6f2ad3ac9a47f63c924df4832d73f732a99f777f324998fb73993ccfb5f7f96ccc7df3a49e6e3514592b9bd3aa664ae1fd6bd646eaf9a2b98f4ddf52573fdb58e60d89f6d49e6df9b13c97c3c1d45326fbf634826ffb2934cfee40086fdf88164de7ff65232d9eb9b646e1fa607867e9bbe641a8f816092cf14f2423f4d070c7d8b9f25f3e7bbaf60e89fb791ccfb3b15df43ffe22f30f42f13f240ffea1b18fab716bf877ee967b043dc92bf1f0ea16fdd9af3a8f740bc3dbe64f2f70bc9bcbfcd2fc9bcbfbd4432f90b4730f5cff55e3297bfc9c0187f732899f4772099c6e35b321f7f6b0fc6f8daa6649aff7692f9f3724d32d7f7cb4932ef6ffb4e32e9b302c6f86723c9dcdefc50326f9ff32e99f7975382a10fd75c32d7e795906742fdd3bd49e6df67a2bdd09ff20886beb89164fefcd54932ef9ffa2c98fca72bda0b7d6a9f25f3feb0c4f842bf9a07b0d02fd13fd0afe2090cffd6c660e85b24ae87be05a40f63e1df8277c9bc7debab643e5e575732efef6e2799cb1bfcf89ecbdbed2573fd5cfd781e1fcf952d98fa3b91cf277f74cd24f3fe0f3ec08807ba8d64ae9fc54232e98f27993faff9f13df787ae680ff4d57995cce57103c95c7fac3bc97c7c7c5f308d67b8028bf9f72299cbd3dc49e6f2981f92797fd69664de5f7e2499dbb33b92ccdb6f2dc1d067772099fca72e99b7ff6a49a6f946f437f4b9bd48267934b0d0ef77c9bc7dad68df9cee9fee25f3fe69447fcc31df88f1843eaf6e92f9f3da89649a0fee25f3f1cb85be41ff0331bed07f5f8ca7f0a7d43f13a1df9d2a99f777f32899dfffea80111faeae92b93cee41f090f7effa0c463ce77f48a6f9ee51321fafeb4930f547bb01433fecb164fe7cff5b321f2f2f92ccfb3f93d793bd745b30f421ae2593bfd94be6fd1b2692b93cde4e32b79fda164ced8ddec1d017e74332f9dbb564de5e772899e299140c7dcaa692b93db8df92797fe61d18fe3117e303fd59b792e979b164de3f8918ff05f5cf46f40ff4c715e301fdb9bd80e13f57f792797fad4a30fce906bf17f3f51ae331c4fc19a13d43f89780e693a9f0a7ed028cebfd4e321fafe6198c7cc00b2473f9bc77c95cdf4a4ff0908fc75a5c8f78bfb52553fcf02999ebbfdf08a6f10e5ec1c2bfdc49a6f97c2b99e6ff27c9642f3fbee7fab416f2407fc299643efe912f99ec692099cbd3b492b9bc9ab8ff94c63711fd0bfdb2a792c93e2ac9140f689229df5125f3feed5660e85ffd2a99fce34432efdfee00867e5e14c9941f8ec0d0bfcc904cf9572a99b7a76e25f3fe73c760a1afaa646ebf99e85fe86f2ec61bfaea0b79e11f0ba12f2eda8bfb4b7d267b98897c64dd81a1cfeb503297afbd934cf1d45e30fc93f81ef363b896ccefbf3a4a26793dc1149fae7d30f247ff2a99ea1d3fbee7fed68b05a31eb1924cf9c2083ca5f6076bc9542fd948e6fa900e2473fdbbbc09463d630246be1a6692f9f84481643edef95532b73f5df01cfd7993ccdb7be92453beb5924cf3c14432efbf5cfc7e01fffa2999e6bfb1646e5f9b022ce2cba364de3e37114cfec132c0d047f74d32f9e37b30f26b2f05431f5763c9bc7f42c1d04797e6cf99d0c71be41fc21fa52a18fe24207d9f0bfd5a1d04d3f8570fe009d573dca3642e7fbb054f697ca237c1246f3a944cf53a5b32c5a72f60f81bd796ccaf4f2bc994af2d2593be6f2453bea682e7345eed4e32d5ff14c9bcbf2f57c95cff7dd15ef8a35097ccdb93cd25537e2bfa6b3124fffd055ec2bfcc24537c548045fe518331decda7647ebd2eda6ba37fc478c01f6d44ffb8d43e1ded17e3af3960cc97f5022cf481e257a6dd149fd96bf08cc6ffe64aa6f92604c35eec4032b7efab2799e2375b30e94b2aae5f50ff58aa642e6fe148a67ce1065e927fb80d2553bd2494cc9fdf3e49a6fc45c863c07e1dc97cfcd3a3606a5f7d05633e887682497faf4bb08df8e2030cfb2bc9de17a2ff4bf49f886762f4cf10f666bd80618f3e8dff92f5177f5e914be6ed2f36e005c91b5f24533cf22598ecafeec04be467ae64f28757b041bfaf5f040f29fe68c0268d9726da63917e14a2bdd0c7f424998f5f44fdb314fd91bf83a18f8105467fdc4660e86783e789fee94a30e215e3118c78a3a0f9dc60fd45fa34072f491fc329d8a0f685a964aae7dfc0265d5f2f05537f568f60d86bb091ccfbe36248e6fad988dfbba85f8e24533e48f66f88fe892b30fa67634ba6f97508467f6d1cb0a827435ed11f35fa6388f9c9a7f8c814f157fd065e92fe5f6e6083e42f5cb0897ac417d8227dca3fc036f55fb305431fba77c1747f3b02bba4df3ad9ab29e42f669229df46fb647fe460d8d3aa0243fecd2758d4bbefc0a21eb403a33f2a8a772c263f6fff35055ba827d1f85aa2bf2f1a58f4f70a8cfb252a18febdf1c0f02701f58f2dda7f5d48a6fe9b8071fff21d2cfc83603caf51c1b87fb106433f4b1a1f87fd17eebf1b17ec903efbd43e46b0f71a0c79cb2d58c4e72d18cf2f1bb078be0dc6f3339abf5cd11f8906c6f5de1a8cf846e3f6c1cbe724df068cf6548964ae3f1b130c7f9096608c7f7603a3bde90e8ce7bb2f60b4d77e00c39f075c9f98f639e47fa34832d7e7f84c2c9eb7ba80216ffb08c6f3cc042cd64f1a30e42f9760d88fe382d19e1ced19c11e42aebf0cf17cd306435ecb04a33d610e16f20b16f1470a16ed3981457cf9443c82bdae2660e19f79bc341c8be7d70e18cfd71ec022df8ac178feaa05e379d72bf108e3df70ff369cc8fe1d8345bc9c81d1fe60452cfaeb7a03c3be74ba7e2adbd382f1fbcb3b18e3910dc1689f4df24e657fd4603cafb2c168bffb0cc6f32b1ebf0c67e2fe01e9d34cdcef1283e12faa6f30ee67f860e1ffe660a1efdc7f0ee7e2fed58c58b6e70cc6ef8d002cd6173db0a83f2dc0d0b78edbf77021e5bd078bf6aec1f87d41fabd14f2155bb0f8fd108cdfeb2330da93de83f1fc8ac6d310f2ac1a309ed772ff3734c5fdb48d64ee0fb72e58d4e75ec0f87d7202a33f0d713df4a5237bb7e4782a60b11ee681d15eed112cee1782a1cf158f4f86b6b8bf6581c5fa2af5a733823f762d30eed7d2efdd11f2efcd1d18d76bdc5e468311f2a3c007e379f5082cea75f760e8fbfa8d782cf49dfba3d150fcbebc030b7bdc83a17f099faf472371ffe64c2ceed73460e883cefb6b3416f7ab4fc463e10f2c30e46b8927e279b94b2cee6f6cc1d087ec092cec4930c6f342f24f85fc46442caef75660e8cf85fb93d18cfd9ec783f1162ceaa37cfe19cdc5fd3ceabfb990d79d80d13eeb152cd64fe9fa85f8de7c05a33df9188cf66cbec0d0c7f50d0c7df3b8ff1f2d85bcce002ce227078ceb1d0f2cfca54e3c41fb6f74bd21ef5780f17c5d058bf53beeaf46e618ebd77a2299c77f5bba9f25c6b7f4c1c2bfbd80d19eeb07f104fda1933cb678de2603e37eba01c6ef6f57b0a8ff71ff3d72c6a8b7e8d47faee88fb507c6effd188cdf3bdc1ec67d38c739e2e3c5a63393e21723269e60fde4f22c99d677b93e307577285eb7b8fd8f27ecfe9cf50e0c7d8a79ff8ca7ec7bfefb6b412cc627db81c57e823730ead9eb1158d43fb8bce399b8fe7a0716eb5d7330c663c3fb733c67eda1fa484d2cc6c39a83a11fed193ca57a651282b13e16f3f96ebc9860bdc8d880c5fe810c2cf21bae8fe3e544d4cb23c93c5ed30a30ea071b170cff92d0f81813d443d71730eaed9a07c6f53eb7b7b1c9bee7fa117c49a6f5024b30c5b3760cb6b19ec9e3adb13331e8face93ccfbaf3883f13c23013ba8a72e05d3fd0d1b8c7c734df23b53d8df86facf9da03e7e1b80f1fc82f7e76430813e6d63e229fa3be5e333194e4cd40b52b04ded31b8fe4e4653110ff2fa0a73a736f28d9a788afd67fa180cfd6a1db0588fe3fe7f32610accfb77c3f59721f2c77c493cc5fe0aaf00e37eb731788afa4e059ed1f8361f60d48f6dde1f93d914ebc7460a46bd2fe4fd37994fc7940f6cbec1e89f98cf5f93a578def5013c433d86da6f4c51bf09b9bd4dcce982f2b39cebcbc49a22fff6b83e4dec29ea15d95932adb704c433acffebf43c776ad1fd039d7886f5d315bf3f5356f09acf77d3d1d4a5fa65734f3cc3fe035d134cf7372c30ec355b824dc413dc3fb0e9906574dcdf79c4e2f74501c6fa5b74104cdfb73c3e9d4ea6d6887f7fdb10b3e791bef1f9940ddf1ceb078fe005f5b7c5e7e3e96c86f58f8d0246fd3a76c1f311f9b377b043e31bf07c693a9fa1de19df816dec07f804bb584fa3fe5accc47a86069e517b82002cd6f775b043f39bc6e3dde9923d8eeb7332035bd47f3705ec60ff824d3cc7fecf84ebefd498c19e2faf609bfa2be6f9f0d49c2d51cff5c016e5fb2b176c8f78fb8b15d8a5fa99c9e7d7a93543fdab1b831dfafde6287844f5d10e8cf1af49bfac39c63bff024f499e98ee6fb3fb937f7d023bd4fed407bb435aafb124d37e2d5d30b53f03cf87d43eeb0d8cf5dd7803c67cb7e1f63d75587f707df1e9fece7c30a2fd5d7b30f6b3469f9269fdc792cce5594dc1587fba52ffb84c1edebecd5e326f7f41faebceb19f2cda8271bfa6133ca2e727e0118d4fb2164cfa9c2892f978af4c30eca1f1c19321d7bf2bff7e3660e34ff5e53bb043cfaf5dc174bf6c0076a97fdb929805acfcfb6d0446bdbee4ed9f0d857eddd660f89b6e2298da5f05c4ac3f687e6bc0c311ad87e07a263f9f0fda77f094da537f8067245fc5f569369a1963d29f2b31eb5fdabfe20ba6e7a777e0d188ff3eb9815906c29fa78227d04f053ca3f6b65c3f6663260fd553a93d2cfca4fec91bc95cfeea041e517f5fb8fece2662fcdd023c86ff33c1d31167cd06cf21cf5c308d679d8017d41f0df72fb3e9cc1ef3ebab14ec8c69bfc05432ed47d38885fe5d4cc9b4fe37028fc8fecb37c9649f25784cf6ebbf82e7f47dbc042fe87e05f5cf4ce8936b82e7f4fb36113ca6f17a002fe8f986b8de80fe8bef4dd28fc292cce52fa68269fc4d1effb0db2f49decd0c0c7fdc92fe2ce6131a3f6d2d98fcb7bf02cf49bf370330d68fea5a30fdde38831dfabea3fe59b2fea178b0009bd41e4f03db23aeff37713decb5f00593fc2df5a7c1ee47eb6f2330eadd17156c8ea87ff7609bfc45590b267f78d5c02e714bfa6ab2f1207ff80136c87ef22918f34dfe06c67cd186c48b018dafcee3cd99c5ee47faa48217647f99609bf4c7a0f1b2160392afa3f6da6cfc68bcd69279ff949f6093daef4ec1f067f5817831a4e76de8f70ebb9ece177c806d6abfb3235ec0dfba2bc9b4df9bc6d7ed1376ae5f5c3fe703263f6f4f520a1e53fc99102f66d4be8cf7cf7cc8e4e3d7673e784c7cdd82a7d4de5a03c3fe751e9f3265c2fca09be009d94fc2e397394b87c99f186bf08cfa4fe3fd3b9fb0e7717dacc792e97c0b8f5f58f8bb20d6793d613e5f2cc7b49fc5005bd49e35b56fb1c4fcecf1fe9e2fd9f7743dfdde582ca83f8267b049ed59f3f9686eb2eb69fd782699d62fa83de67244f67de1fa3eb79643b237ef2698f4ab9e8347d4feb0008fc99e1c6a8fbd70d05f4762261e6f9f46e3e730a6f3160618fdbbe6f9c6dc5d0ea8bd0df5bf6b88f89aebdfa25f00a5f8ff4e32edd749c0636aff66019ee17939780e7de2f92a73f643e8bb031e537b7c133c237bf5dec073ba7f44f71f1a225ea3e78f447f79dfe011ddcfe3f22dc68c29feff06e379ba0e9ed2ef0b1effb1747d44f3b1fd0d5ed2f78d0236c65cdf367c7e5fb0009858bf07cfd15f7bf082f4a3492473f96f19d8257b6df8f82e66cb05f55fbe223630ff6f797cbc98b3f67079527afe82319d17e1f6b7581a03fafdc693ccc7d7a0fb194b97da7bbb111b63f2af1bae9f0bd31810eb7cbd61612d1dd2bf94da671943c8cfe7af856d8c69be6e0563be594f2573fdd7b8bd2c1c763ded0f53c01392c7bb4ae6fdd3717d5db8c684fa4bbb134cdfa767f094e28180fba3e5c080fff15fc0b309f5ef9764d24ff13dfc43cae7a3e5d0807d6cf8782d47acbdfcfeed0b783ea1fad50ebca0ef6f3ed82079a32f30f2c5644f6c627f5acce7df655fd0e1e3930460a662dc3f1cc14beaaf40133ca178a8069bf47cdf90ccc74ff3c10e8de78dfa676c8afd09b564daff5982b1ff36a6f64c58ffd2fed40b7836a1fac504bc9c50fd6101c6fc97abc426e2b3700fc67911f3018cf33ac99d643e1edd198cf3176e07463da4fa0063bf8826be47bd53e7fe773965e345fded806db217eb1d8c78f29612b3f6923ea9603cbffb0663bf4949d7b38083c663b3022f68fceb7bb043f6118682a9ff8c02ec92bfcbe9fe7dba49f5c30d18fb636c9e2f2ce7ecf7144f2a6097e4bbe5c4ecf7140fcdc0b0b734018bfde03a784af3c53504cfb15f47dc0ffb0bbb8160ecbffc002fa95e58edc1d8bf1a4dc1163d2f36c1a8575495609c5f1a4aa6f3a134febd83e2ed2f376093faafa3e72fcc01f1f50b3c217ddd5660ac37ad63f00cfe5407cf69beef5230ea35c6026c60bfe55532e55b39d8a4eb6f73b0d8df20ee6f637fe04a32cdff03b043fd757b904cf9d9168c7ae7ed2299ce7b3692697fc898d8c2f99ddb128cf3b317f49f85fa6348f75f1a06d9afb604c37ff817b04dfa1c0ec10ee9bb4ef22ecd015d7fdd8047345eb5079e907e598e60d2d7b40363ffe3762598e2d5750e16e703d692297ffc128cf35768af897afb36108cfaee5c32d56b0f9269fe2e24f3f61731d880ff5125d37ed80558ac974c25d37ec09d64de7fe64132f73fea27d8a2f15732c9b4bea008a6f655a23fb1dfb28c24d3fe470d8c7ae1ed5132e95b2099cf8fa6e82fd4e3c32fc9b4bee3125b38ef7723ff641816d99b7d03dbe48fc22bd8a1f9f95a825d9adf4af28706eb1ede5eaf060fe97aaf133ca1fc5605237e6d8ee009e5bbd5198cf58b4efc1efb6fb71730f67bae66e025c5df8a09c6fecae020998fafd248a6f3ba909fd93b6f4f71025bb0af52329ddf9849e6cf533fc036e993924ba6f96726993f2fcec00ef57ff12e99e2c34a32ed7f0cc1f017d5bb649aef7cc9bc3f22f13c97fa4fc3f859388f5a6d25f3f69443c1d86f3b06e37c4be54ae6edd354c9bc7dd791643aefdc4aa67acf2b18e7f134f13dced325a4ef26d3379affc95f9826e2cb952a99c6f7153ca57835fd0463ff691108267fb579028b78c2001b34dee14532bf7f62814df88b4832d52f2ab085f59d0118eba3752899ecff2699eae307c9b43fb405431f9454329d2fbb97ccdb938cc02ee95b2adaebd2f8b590dfc279e448974ce3f12998e67b4d30ce074713c934ff403e0be72d2dba9fc5e607defeca014fc85f5413f094e2313b954cfea0114cfe467901233fd41792a99e6a49a6f527c198afd71bc9549fb9822dea8fba944cf9502799dad782b17e6d7592c9be6782495fea42321fdff8c7f77cbcb477b043fa1deb9229ff4904e37cc697641a7f0decd27828aa647abfc45032ade7b982495f13b25fcbc2fb0c944032d9cb93606abf5949a6f314cf60bc4fc00a24f3f6b79960d29f5a914cf11dfa53d87bf82999d6df303e16ceb755a4cf369b3fc8ff7660ec3f57de04933ff0f760ac5f665bc114df2b67c1a44f57156c507f5f1cc9b49ff3198cfdc69bab60aac7ac4f601be7fd22c1781fc95132ddaf95ccdbabd492b93e794f60e883229e87fd9ef959326fbf3a964cf9e00318fe5d9d4be6fda192fed916ce83a92f92a93dbe64ca8fd11f229e4c6f92f9f3938164ca1f4f82b1fe994ae6df871f60acf79a6bc9bc7f62f49785f3b1b75230d95775914cf30bfacfc279b22df90f47c413a621995f9f7be011f99b6d2b98e2136d021e4f683d63059e4cb83e7ae2fa19dd4f3b83e734df943118f581f22099cba33c8397549f592dc026d69b8f9279fb6f9f60e453d6156c537f5a63c9644f8160aa47695330fc8dee0aa6e7c5b964f28791648a6fe692297e580aa6fa6628da8bf8c3bc974cf9642118fa38954cf58f89649acf1692e93c27e9936361ffbdd149e6df2b9e609c1f7d96ccf549ad24d37974e887d0676721998f8fba924cf1fa9364b247713df687754f92e9fc672399ea45a23d581f35af92f9f7b9f81eef13885ac1181f4b32d5dfa10f16f6a3044bc974dee9158cfd3f892399fcbb2d993fff26fa6786fd3ba23f711ef146d7bbcc7e283f7b944ce7995ec0639aafab25784af671db0a9e52feb200cfc9fe320f2cec650f5e52beae7d49a6f319e2fe4bd457766083f453bf80b11fa878154cf6b2adc1585f37c4fde0af235530f251717fc45b9e90d7c17ca848a67add5530ad1f74a160aa8f76e279c8e7c34630f97f3b174cf2379a645abf247fe35a781f90ff2818f3c1443297571d49a67cfd4930cd87da1b58e8ff5630ece74b32cd1fa564aaef7982697dc87900633f73694ae6faa0be4aa6fd789a648aa724637fd25a32ed3f79924ceb3d3330f6f325ad64de1fd98364927f2598facbd42553fd3594ccafcf311e16cecbdf22c95c5e652a99de7f267e8ff3c9e1bb641a6f4732bf3efb008bfd812f92297eb32473794b31bec87fa30a2ccea3ee0493ff30f79269bfe23718f53e6b2099ea0377609c7f34be2453fc7b914cf91c1f2f63c0e6478a0fb6e019d58be207c1538aff8fe039e503712b99e6eb5c3297a750c04b1afff22618fb1922c1347fc73bc9b47f4630f2f9eda360b2efab2e98fcd1ea158cfd83452598f47f6b48e6cf8feec1a8b7a40bc1f05f3bc9bcffb61918f596f85d32d5e3447fbaa48ff94030f6ffdc24737bf267c416f6a7ac3f2453fe580bc67e99122cceeb9c24533d6b2299f4ad108cfce30773fd500cc9341f7792a9fe6b0ba6f5da6b2399ce372ec1d85f1d9d25f3efd59b60f89f3bc9bc3fd4a364f22f6f60ec97543792797fa8a960d8c74d32f9932918f61ed49269ff832d99e44d24f3f61a23c1d43f96fc1ef1fe1c8cf763448e645a3f16cfc3fe3d632899e2955832cdafd01f0be7d5ad4a32ad9f3792b9fcc64030ced3d792b93e9723c9b41feb02c6fe67732b99f68b7c4aa6faa3180f9c17f6499ffa032dc46bf098ec5d8f24d3fe08133ca1f530ed049e527eb7f50593ffb83c48a6fd570a7846f7d36b30e6fff25b32d5ab73c1145f28ef82299ed1e660d473b64f92a9def92698fcdd5a3cdf46fd24914cfbcd74c9b43e21e445fda611f7437cb1fe124cf65edcc02edd3f7225d3fb001e05d3fc5ebd108b7879bb93ccfbc72f05937e66a9605abf538e92493f56e021d99f6249a6fa5b2b98fc9f72914cedc3785a789f52f12698e42943c964ef17c9e40fe792697e1849e6f2648e60ac470660bc9f243b4aa6fd3fa1647ebda20826f9d24c32ef0ff55e32d5d7447f60fe2f9f25933f5a4aa6f8e62c18f9502299f40ffa61e1fd4b4a2899f6279492495ed19e29e297028cf795048d64dedef05530e29137c9e47fe4efb19f740cc6fed152134ced0f55c9fcfb488c17dedf74b9934cf64dfa3c326754ffab0cc1643f510ac67a78ba04633e77466083ecb309c026cdffa921998f476582b19fa7ba0aa6f93e5e0ba6fca6188051bf4b447bb1bf4aff00237ff60f92e9fd41f792e9bc7d2599e6f717c1d8cf247e8f7a5d160ba6fecf23c1b4bf21a0f86264e13c72f82499f2fd57c1f06727c954bfcec098df755b30d9ef7a2e98ecdf78974cf54cb447d47b3d5330e2cb0fc9b4df47dc0ffbd12ea9647a9fec1e2cde07f92e99f60b1c05239e3e4ba6f9df974cf9d74932ed9ffff17b2e5f70014f90ef288261df8664b25f5332bd6f0ae36be1fc4ef92499f22d4b3297ff593c0fefb7525dc9e4df3c30de5fa53a9229feb12553bc2ec66f46f2565f92c97f37609ca7b4df25d37e825a32adff89fba39eaafb92293fea24f3ebb7627cb13ebbfd944cfbadbf2453fe37154cf287a664d257d15e715e80fa6fcce673f2af117846f94076075e503d2188c1d88f9a9b82c91f2457c954cf38832df2279ba9647adfe70a8cfaecf62098e2ef6e2699ce27ed04533cb2d5c0d8efaa3c09a6fa46f12199ec5d3c0feba51dcd9f63517f5dbd0886bd3f4be6d76f7f30d59b62c164afde5432d5271f2453bdf0118c7abd77124ced4f1ac914afae2553bd5edc0ff3b9f32498ec6d1308a6f66c55c9341fdd83313f9ba23da8ef46a564dabf664aa6fd21f27b8a37e291643abfe249a6f9ce174cfb13a2028cf78b25b9647a1fd4a364f20fdf92c97f0c25d37a512599d607a03f22bf375ac994ffa49229ff78944cf94a2618fe48fe1ef59e4632bd3f270163becf2ac994bf8beb71fe4b0d2453bd27964cf552d13fa807da2f9269ff612499e627d13ed40f424330b55f13d763bfc6ed4332c50f37c1f0f78a64daff3d964cfb43c578637daf7a138cfd39429f719e6745fa30314df21f590ec6fedd32134cfbb10c5d30f98bcb8b64da2f3c01dbd87fbc174cf5c92001e37c4d25eee760fff1b7605a0fc8b792e9fc81b8bf43f149740263ff68fe2a989eb722fb9c8878201849a6f75f9e25d3f37cc974fee15532bdaf752898ecdd0904d37a475080512faf7e30e9432e18e7f56e82914f5482c91e0bf13ce4ff7e2698c627fb924cebcfe2f7d8ff1b3e80719eaa934cfaee3992491e717ff80f6f2699f22ff13dcecfa753c9e4bf0e92293f394aa6fd139660b2cfc8904cf9df4230e68b4a32add78bf1c0feda740ec6fbebcab3648a8f2792c95fd492299e1848a67ccd164cf25b2d58f887ab64f2379d64de3fea4132bd6f4efc7e8e7827944cfb7f1e2553bd4f134cfa6c799269ffb6781eea8df14432b57f2718ebe591645a2f8b05231f15bfc77e0f652699e229f13cbc7faa9a4ba6f361427fb03f5013fa8cf5e2c495ccbfd73dc924af180fec0fd33e24737922f17c9c6f6cc91ea626f69b5e13f082fccfe64d32d547bfc0385f565ec0886fba1cecd07a663394ccfb237b05633d627b144cf6779949a6f75fd682c93f06349f4dc5fa433d154cfaace982697d721b4aa6f3c11918f585742299fce5bd64aa67958229be5ac560ac27ac12c178bfd79b64da0ff1e37b7adf95fc3dcef70592a95ebb174cfe3a10cf47fda01c08c67e1b5f32bdcfb0134cfde12a92493ed17f585fc81f25d378dc49a6f8e253308d57249e3f417c7a904cfbcd7e30c5d382b11e982592797f24df82b1de954ba67aa6907f4af69baec138af6c8d24533d692f99ea733bc1e4ff3c0b2cde37be944cfe712499f2b1b964b2675732c52bd0670bfb45d54832e58fba64da0fb301e3fd8d4a2499d67f857ee0fc72f82d99be5f81713e3e194aa6fd49e27e588fb89ec1884fae13c9d4ffa27fb0bff0229e67537fae481f66e612fb2d776083ec3debc026eaa53618f18a3b0323fe580f04d3f5c98b64da7f63825df217852e99ce77907c33113f6c4dc134df6f1f24d37c9982b17ee04f05537b9a77c9148f88dfa3deb07a92ccfb7f73168cf365778229be48bf25537d19f28bf501e55e309d4fc94f92c97fcec158cf2b12c1e41fbb4fc9b43e3d104cf3f7f6158cf87ebb170cffe448267942c1e47fba05187f1f455049a6f5614330f4ff0d8cf3b88ab83fde3770d94ba6fafc12bca0f6a557c1c80f6dc9644fb964aa7f1492a99eb1934cf3f718bc44fd632199f2ab67c914bfd782518f16e389f78346a23dd8bfa58c25d379ba4030c95b5f2453fc5c824deacfec2299f6eb6c25d37ae74630e2b94632ad170bf9b13fb87b964cf514713df61bd4aa643a9f0f7bb31cecbf10fa28f6e3f89269bd83e2adb9399f52bd33032fa6fcfef9086cd07e8d95f81eeb1b97a964b2bf0dd8a2f958ff02dbb41fbbbb825d9a3f2eb5608a3fe28560caafb6141fcd45fdb11a83b11e180f05d37e5c5f114cfe669d8051ef6f3dc1a40fab108cf3d9e55a30ce3b1a60d4d78bab649a5fe5f7645f978364dededbb360f247452899ea616730d6e7d6779269fdfb4330f9bbd4148cf8e7058cf5b8e44932bdffe25e30f6835c24d3f9d1b964b27f713decdd16ed9b937fd2f792a99ed2082679a247b0380f33964cf3ab18af05c52f57d1df381f5baf2453bcff0046fcacfe60daaf6a4aa6f9ed4b30ce7fce25d3fedd1918f65f8af1c37e6d4f954cf9cf5a32c927fa17fbede254326faf22aec77c1bd582a9fd971d58ecef3524d3fe5ea1bfd84f97d1f82ec47a83be124cf5c8ca07dba4efbab8de9df2dffba44f0b51afeb5cc1747d32154cf61eecc043ccf74f9269ffd3098cf7495c1e25d3f9c14a30ad9f281f92693de2001ee3bcf34430e94f71114cfe259883f17ef6b52599de2f36144cfaa23c4aa6fafd188cfa79d60a267de832c1345f1786649a3f7e30cd97a2bdc86ff55232c54fb9648a6fc4f367e44fbaa1649a5f669269ffb7f87e4ef6915f2453beaf4ba6f9443c1feb655a2c99e47b944cfb532493ff6bef25d3f86ec1e2bc532318ef1712fa82f3cdc55e32b5ff1b0c7b5acd25d3df9fa04ba67ac25e32bd0f44b4cfc0f95ad13f787f759c08c6fb8f34c9141f6e2453fee80b46fe22fac7c2fbafef24933f17fa8efdf9590dc6fb8d4a8a079626ceb3d513b04bfa5a527cb664f645eb65067848f359fd8369bfec063cc27ae45532d5e31f25f3f15c3d83315f5d12c9544f740553fe1e6592a93f3dc158bfb88127145ffb9560b2873a96cce5d75f25537ce90ba6fa62f283a95e2ae49bd2f82b0f82c93ef385645a6f17ed453d39984aa6fac04c32fdfd5607c1a42ff14a30cdb7b74232e5a76f60e483fe5132cdafb960c4fb5f60c4aba52218ebaf7b30d69fb6e27b9c1f0ceec1d82f962b92c95f1d24537da7148cf93d05239f534f92e9bc8bb81fcefb1547c9544fabc1383fe68af1c67e92f807d3fe43213ff6af7662fcb19fdaa37cc410f5ebfc5e30cd1f6b07ecd2f85a347e06332faa8f1cc0d0efdb17784cf6e91a82499ff44ff004eb318f92693fdebd649adf5f05937efa67c1347fe91618e7bb6e7782112faa60ac8736a1601a8fac00a31ee98c05e37d155bc1347ff8aa647a1fc009bca0f1f21682c99f9ae2fe0b6acf360763fd62bb168cfcb0148cf7790879f1be9ad4954cf53cd17fd8bfe49f24533db1164cfdbd7d07e33cd346fc1efb17b789643a4f300423bf303760bcdfec42f669b27885ee47f38169e1bc977e124cf18d3706e3fd11fa163c22fdda9482a7b43e7805c3ff058660ba9f2b9e87f364d14632d5fb4792e9ef37fe02e33cd926028bf364efe039c9b712f747fdd9ad24d3f58231fee58b601affdb9b648a6f7230dedfe12d25d3fa760a467d3817f218145fd99f9269bda1924cefdf93df23fe7e009b349f98623c2c1a5ffb2298ee97d8609c3f32e6609c3f8b2cc9646f0bc914cf3f4aa6786607c6fe958ee20f8bcdafb43f81e20b165e93fe5c3e25d37e30f13dea3ddd093cc27ede2d18f5983804e3fd1d9a25989ed7168269ff61fa089e223f9e8167d47f862699d6f39e25d3fe68152ce2b70318e7c9ec67c9f4fe12138cf70f252918f1932b9e67507caf08f9f1be9938069b648fc15e308dbf32108cf7df88e7637f627c150cff7a0163ff42f000c6f99c88ec9b4d37a867d1fc62b3f1a3fd3c743f5b8c5ff102463cb2da82117fb4df9269bde12498ec510f25d3fef01c8cfcb8b425d37eaa5232bd5f2506235ed85a9269bda4154ce31d89f6cef17ea8037841f76b447b17d84fb6012fa9fd6b211fea49978b608a4f0c156c423f3bc9b49f3602c31e6f7bc1d0bf4a32c50fe44f6c1bfb3be22918e7e93a6287d907adb70ec063eacfd51b784afdb3d1c0c85f8a5232cd97afe0398ddf652d99fcf75130e5879d09c67c961482c97eae7bb049f74b3ac9349e86649a4f2692b93cb978be8df749b88229be509660eca7f39f24d3f922713dd6afaedf8269bcd690c7c6f9d755001e52bc5b533ceb5a63d29fab2199ce63edc1139a9f82083c25f9f5068cf745dd2cf082c6238d25d3fb1d378229bf503ec178dfce6a0946fce9bd0aa6fe5ccf04e37d0af27aca77ac1bd8a2e747df9229fe2dc136f98ffc4530e9f34a934cf9f10fa6e78be739387f48fde9daa8f7273c3e310716f67b260f9269ffde1318efefb91e24537dcd06e3fd79f6156ca0deb1904cf6a080d1fe6a2199e67b5f303d4fbb801dd8fb0a8cf8f9a611db78ff5dac8211df745f60d413133e7e2c389be17ccc183c27ff97459279ffac4b30de27947e0826f94c4532bd7f5d032fa9fd6d2a784af58e21d8a0f9e1aa48a6f53f5b30d58ffd6730de5f94ad89ed01d9ef86eb2b0b2eb0feac6fc04b92af7525d3fbcd8f6093fccde64532d9cb4d30c57fe1128cfd33eb77c1a41feb028cf7355a1f82e9f9ee1cec62ffea9b60f227892918e785f0bd8dfdafe9b3601a4f270463fda81980f17ea59adbbf3966fd41ef472dc14bf2075b1b6c60fdec4132d50f0bc9944f1cc126c693dad7bf5e9ff2075c6f63bd6b45fd33b1e6549fb8adc0580fdc7682c97fdd5ab035a5f74309c67961e50bec523c1de2f736eaf7f11c3ca4feaba8bfa6d664467fffdc080c7f53b492a97e6f08a6f686776013fab4964cf69982717ed224ff30b5b15fe81608c6fbd3ce60c48b2d8dd78cdd8ff2eb5430c5839b5730f2dff60086be74a4af33d6ff148fdd8391ff6a74bf390b30693de808b6917f64c436ce8fdf1230f6bfb7345e0b6b3a27fbe9c0f319bdaf8bfcc782a5f7e43f0f60cc4705f99f256b3fedf71c826d92ef3625b627349f68dcdf9b2c9f9b927f237d3458ffd1fc5b8327f007241f530f1aaf6b00467cad51ffb2f8674efd41fed5b6711ed0e4fac192cf39b57733022fe97ecf977feda32abf7d8c9f3e26ffa7827fa74fcf0afb9da5daaac3fe58ff6a0be8f3df21cb2f72b9ecf3bb5c0afe9b90afff77f7df5116d62247f5d81ffad87ddba87590cbfd87bfb3f1f9779605f20899fa6be8cfffb79fff167b71e9f393743ffadc1663f4e33aa96fbdedf8eccf3f18b9ffff65e16dfbc90e6009240d1fa9bf2b3bc9439ee0df4d1661eb3f64f9313a3f24f3e4e717cbfa7791e5379fecfefa91d758f05a8e94457a8a7f2b590235542335561335553335570b364ea55aa917b5669f86e951ab76ec7365b2de544dd5d99f15ff9dc67eb1fe379365a3aed827652391a85bf6b963d2ecd43dfbec982c07464726dd91fdfb4e3da9f74cce7bf5817d0c76e53ff4daff5b6479e43dfdc446e699fddb597d515fb94ebda9efea87faa906ec9a9449f8c524f85607ea501da96375a24ed5993a67d2fc1bc9c25a7a5637ec9f91ba607f02d8fd92c9f2cafe6929aafaa4284cc7be15431d2ba662b18fad380af31a8aa7f8ff3d92fcf7cc954aa0844aa4c44aa2a44aa6e44ccf5ca63d2dfbf4b6622a059b45064aa954ca45a9954669954eb92a3745537465a5acffe8b5ff37cab251b6ca9db253cf8aa2ec95036bf1513929f7ca83f2a83c29cfca5979515e9537e55df9503e952ff6dfbf9581325446ca589928d37f23596c65a6cc9505d3b393b26413cd83f261288661b044c0b00dc7700dcff08dc0088dc8888dc4488dccc88dc2288dcab8a87746fddf23c99f9345b58ca6ff23a390df6677a3353ae36adc0ccdd08d95b13636c6d6b83376c69efd391847e364dcb3cf897d8e8c1fd8e7d178329e8db3f162bc1a6fc6bbf1c1b4b0cf02685e757f9b797f9aadfe999ff8af6561527c1a5feccfb7313086c6c818315fd4186363624c8d194b9916c6b2370ad3304dd3326de3683aa68b8fc73ebe19b04f684666c465eaa53a9a31936a6726666a66666e16666956e6c5accdc66ccdcebc9a375333757365aecdcd2f33b1f2eb1cfcd764311a736bde3169becd9db9e7b21ccc8379344fe6bdf9603e9a4fe6b379365fcc57f3cd7c373fcc4ff38b7dbecd8139c467648ed967c23e63736aceccb9b960992a3334e3de322cd3b22cdb722cd7f22cdf0aacd08aacd84aacd4caacdc2aac12b9dc2f91c5ffaa2c56655dac4b3f2e566d0cad5a3d5b8dd55a9d75b56e9666e9d6ca5a5b1bd6d3f7ccd96ead3bd6522689b5b3f61677bfd6019f2393666a9dac7beb817d1ead27ebd93ab351da592fd6abf566bd5b1fd6274b98bf5884b0601e3d61b3e9c0faeea3cf1fd1d1bfa2634cb31a8bfe82f001fff74a89aca135b2c6d6c49a5a336b6e2d7acdb196cc74fa4a9ed18f85b5b34d48f2439643bf4c614e6ddb766cd77ab03ddbb7033bb42326cfc178b4633bb1533bb37336abda766197ea935dd997de92fecce74fc932307756cdc6646055aa67d77663b776675fed9badd9ba71303fec95bdb6376c249ef9676fed9924625414662bcc5e602bf766681bf6d6beb377f6de3eb0cfde3eda27fb9e8debde7eb01fed27fbd93eb319d7b35fec57656fbfb1d1b07efffcafc9f27cb16a66274cb78cc6f8b4df992c1ff6a7fd657fdb037bc8faf3c47a7864bbe6dc1edb137b6a2db924bb7e64fab161ff9cb1f6ce85fd9b91bdb0972c485698ddcc1dc3311d662c8eed384cd2bde33a9ee33b8113b218f5dd89545df17fcdecfe155954d7183ab113333bb1edda499cd4c9ec2f27778a5e0ea7640ff0ed3d6b55653d3b17361acf4cc706cc6216dc6ed8ff3b356b6be3b44ca6b9d3998173756e8e66f7938feeac9cb5b3b1b7ecf78eb365d21c8d9d73e7ec9cbd73708ecec9b9771e7ec9107ecb7a7eb6a03f234b2f09f3c683fe7ecea3f3e43c3b67e7c58cadb33db1ced6b33d6656cc3ece2b6b5dc5dab5c0a7f765ec63cfe9e374f8bc39efbd24f6d20e9d0f66fd47e7d3f9ea7fe954ce379366dffff5f6cec8e9ff5acca933b3eb9fe4f8576599ab9db3b05f9c25fba1e21a6ce2b08c23f34accd3bab6ebb8aebd702a73e17ab66b1f5d9ff9a8931b981fccdacfaca5f76ec86c2ae673e6d18ddcd84d98bde0e3746e6a7acc73b02b594fbcd93336be67377373b7704bb7722f6e6d176e63356e6b358ae67656f3afe8987a70afaaeddeecd6d55cdd5db96b3626cfeec6dd9a43f7ceddb97b3622dbde86dd837bb4576e6031ed331df7e4debb0feea3fbe43e1b817b765fdc472195fbeabeb9efec5707f7c3f9703fdd2ff7db1db84377c474f1c0fe7dec4edca93b73e7eec25daabd2f6091b8a7aa81f70fbdda9f91c533d8f46d79b6e778ae937b9e71b2179eef055ec8e4601fdbf0222ff612e6030eb6d1eb8c977a99977b85577a9577f16aaff15aaff3aedecdd33cdd5b796b36e7c7c6c9db785befce7a70471ebb0b1b5d9dfd3ff36fde8e59cec1db7b07efe89dbc7bb5f01e58467af31ebcc71f5af5bb1ff853b23c79cfded97bf15ebd37a730637362dbde3bd32f2e099368cbe6f229b39ae7de76bd0fefd3fbf2bebd8137f446ded89b78536fe6cdbd85b76441d7a3aff8866ffa966ffb8e71f45ddfb31e7c9ff9e8ad6df8811ff663e547ee8069e4831ffb899ffa198bd6be51bffd523c9189fe75599e2f7eee177ee957fec5af0d6603e6d46f7a49fc967d3aff6acead27ffd6cf77bee6ebfeca5ffb1b7febdff93b7fef1ffca37f62f966a2bef8f78aea3ff88ffe93ffec9ffd17ffd57ff3df8da3bdf03ffc4fff8bf9f485bd30c74ee57ffb037fe88f8cbd3ff627fed49ff9737fa1382c27fd6679f70f597ea97dfc99d8d25f066aa004060b112da65f6aff97c0f7fae5b7811d38fe3570cd0fe31478811f04411844411c24411a64411e14411954c14509839a7d1afb3d68838ee59af3e06a3f07b7400bf460c5fc48ef0d9560ddeb99ad30d906f6c27a0e36ecaedbe02ed8057ba50e0e4a191c8353708f0af54f35ab3f2d8b1d3c048fc153f01c9ccdd829ad73f012bcf6da15bc05ef81137c049fccf38c83afe03b1804c360148c8309fb330d66c19c49b47016c1325443253442d3188416fbc39c71e8865ee88741188651c86cc73a8709f3cb4698f29881c50f61d6fbfc300f8bb00cabf012d661e32fd421d3b41fb2387f94e5e77af6cf63d25f1db661175ec39b19875aa8b3bbafac636f27e13a5c33795e8c7b2f0d37e136bc0b77e13e3c84c7f014de870fe163f8143e8767f52d7c095fc337ab08dfc38ff033fc62d2982c22f6d97ff90e07e1301c8563e3184ed82cb40dd6e1943d63e6ee99fd7c9b53f6dfe7e1225c466aa428456444e68fcacdaf5a46b288ff862c28f1d4c8525fd5d7c88e1c7f19b9e673e41987c8376751c02375a61351c8e2f7cf88e524511c25511a65c62dca8347ab65f369cafe3c4645f01895aa1255d125aaa3266a5910d345d7e8166966678ccc75d4467ab48ad6d126da4677c629da452c82f0039ef778d68ecdb40bf6bc7d74888ed129ba77d2e8217aecefcdabed866af4d1eeaff6f2932c068fb043b77516ca2e7a8a9ea373f4629ea357f6a437e6750d16a79ca37773c2e6e8aad7eae823fa8cbea2ef68a0ce153f1a2aea8f2a2c7f9e1b8da27134096d2b8ca6d1cc8aa379b48896b11a2b56111b319bac629b85166eccbc3d9f73962c7f93b29843e33ef6e3200ea3fb388ae3f081f554cadbcafc5a1f25fe2c0b7ff68f7131d4f8f9e22cd4f73889d3388bf3b888cbb86277bcb0f87111d7d6dedd5b4f7c2639b959dcc46ddcc557ff515dfdb4f662cb3bbaca5875e25bacc5ba3f8b57f13adec4dbf82edec57ba5890fea323ec6a7f83e7e881fe327e3143fb3d866c9bc7380b86e689de373fc120ce2d76011bfc5effd88736b3055a38fdeff992c0ad34726cb6b9cb8adba8a3f4c23fe649db7641ec6b09ee3da665ed3fc0c33f6dcaff83b1ec4c378a456eaca7e51ee94713c862c3c1eecff9dfdb7493c55f57816cfe345bc4c54e3c17e4894c448ccc44aecc449dcc44bfc24484263efde9b3e8bd8d887e7a42c3b65f3d6d17c4da2244e92244db2a84872b1baf07765b1c886f8155b36bbb2fe65914fa2b8499194e69b71f26fd69e8dc9d9b998dff6c13ad953e39054c925a99326d6d5f7beea9db4ccca52f40d55c1d97d95bb385332bb4abae49adc12cd38252ceb4956c93ad924dbe42eba26bb641f1c9243724cd82c657a8ec272014364d94c9b4b2f4dee9387e4d158264f09b34ab146d2e722ff4c96e499f5e198e50e2bf6efe7e4257935dfad3e3f3f276f56ff8afa7df26ece8dfb709c7c249fc957f29d0c143d192a8b64c4abe3bdc7b4fbac8dc9c264b2df93713231de9269324be6c63159d8c76469c6a99a2aa9919aa995daa9e3dfa76eeaa5bef1603a2cbfe1b2f45910cb54b769601cd3308dd2384dd294cbc2d76dfa7cc4180aaff6932c96b0fe3453466e6b97cc8e9d344f8bb4343fd22a4c98f75a5afdfe8687f4621becee75daa46ddaa5d7d451f4a04b6fa996ea91c9fd3f978549c3644957e93adda4dbf42eddb15fedd3837d4c8fe9c9d8a7f7e943fa18fae953642b7a344c9fd373fa92bed2c8902c2ca7db4681719fbea5efe947fa997ef5feb197a56f7f9f5bfd2acb8f91e17a78607dbb5412ff2139a7dfce9069eb673ae86da5f7c54ee5fa696f8f553a4ac7e9249da6b3a4b50b65c3f42c5177fe23ef31361a7d0edad724d379ba4897999a29c63163f971b4efb3e3ccecb3e2649559999d39ea57ea0475e6665ee66781e9fa81a3a06ab0eb675096e1c5599845599c25ce23b3172e8b6af5b9d52fb2889a9add3f99d14efd4a064ccf952c553eb2cc74cc2fe61b077dcecbf477613d982316e37efaeb2ccf8aaccc2a61e7e45b98b34db24b56678d5dc763f53b6bb32ebb662c62f343d6df6ff6c2fd66de9c652c99661ce3a74ccf56d93adb306bd3b36d76e74efa5999c53363a603cf76bfcd8445369691edb23d93e5901db313d31d85db7491ddff268bf28b2ca67a973d3032b24743c99eb82ccc37f67d642ebcc4661146f69c9db397ec357bcbde852c1855577d4bdaec23fb8c9e93419a655fd97736c8d8e866a36cec8eb24936355da7cc66d9bcf7ebacbf17d93257734509552b377233b7723b77d8377d3d6dc29edad74398b7cedddccbfdec900779a828ff4496be024a7dabf8bd36f63edacc23c330ee982cbd97efed70c024619219f7799c27fe364ff32c3c30597eac4172bf95e779919779a556f925aff3266f8d63dee5d75eb7dc613f1ef9cdfdeeb3e25cb316f153aee7ab7cad9eed32dfe4dbfcced67396c1b09879c8729a4bafd9feb7719f29f93e3fe4c73cc88e4c9b1392c52afe812cbd0f559209d332db2ed5263f1926f32baed05ca6678eed5877ecbfbce6f7fe5dfe104cf347a3fd690d92d97afe943f671725cecff94bfe9abfe5ef7dd4937ff49909af719cddaf6cca73628dcd8871fe997fe5dff9404d9cc833f3613ecac7f1579ff1997dbc4c51b4cfee30c9a7f92cc9988e1d59a699f47e377c0bdffe200bb75792259fab7b854d65ea77be302c63cfd2fb1dd5bc481673943bf9b2500b8545f5b3e8814547b6dcabc0575793b1fa919f0ba33059b7d9ac557d2cbfe8f312ebaeb7e4c2e96b1785cb62ad53e1157e111461112923d52ee22229d22233f67d5ec365611ac6aecdd98cb92f8aa22caa3c2459faf6b398f5f597f9e5375958c6b34f6fcc62be8b0b7be4ce74a97227646177ae8ba6688b2e288a6b714bf25f7684303d53fc645268855eac8ab5710835e7b597a5d8b06cabaf6a7ef4d5be60cd243916dbe2aed815fbe2a0d8c5317b284ec57df1503c16cc3efa1a279764614e0b268f7128cec54bf15abcfd248b1aaa7f57164fcab22bde59fe742a3ed894b5efa33c5420875c9645f1597c15dfc5a01806398ba2c90bffd8555114a3625c4c8a692f4931ebd72c989ea8c5bc8f467b5b6677e03163b12cd5ecbb544287c540d7d250c2d22cadd22e9dd2354ebc22c2ae36c7f6a1f498cdc6a55f06e1ae64290dd731f7efc822d654c40cf3adb665c472b053191b2ecbef852cfb5e16f3cb3a9749999659996749745f163f564a7824669465599597b22e9b5e92b2cd34661b565f3b6371dc985bb4e10ffaaca7ecca6b79b3be4acd0a4a9d8d67c4a45995eb72536e992cbabdeda326368e5bebbecf64cabb7257ee7b591425cd7a6d28b552fb45961fd13ef773ea8dcd103b75c56439183e1bebc81c5b7d3d2cb0674e63cfcb63792aefcb87f2b17c6271ce86e527a398c594ca9d5d97cfe5b97c295fcbb7f29d79d12eef32adafee9bb3bebec13f337b5f7eb079bc2c3fcbaff2bb1c985d392c47e5b89c94d3c42d67e5bc5c944be3c45c7d156a7c4c0f665f1939564a655466d06746a7e0d4ef2ab2aadf62fedefb3059d8b7663f36c8d834bbaa2c26cbbd19b2deec97483a264b6b06c6a1b22bc79bc5e3a00996e5c4dc562e538ba86236cfa29545e5574115329fca66bb3ea736471513d73a313946fd9a4515dbdb2aa9d22aabf2aaa84a2bacaaea52d55553b5556745c1b1ba062b362e5ba7a355b57ebda3aff254b74aabf42467b21c83a36ad9f51f641151a5cf6571d488e9e246bd315559556b264bc4662c268b193269f64c96a37bf65a6fae2e2387e9eb5bb5a9b6d55db5abf6cab53a54c7ea54f575e17be6c717d681c5d5233e26a3fe2ebd3d570f4c96c7eaa97af646d5b97ab1aaead5dc556fd57bf5517d565ff128afabef5e966ac07ac2e5f5cf678bddb11a56a36a9ce4ce23c6c5339adf627e4bca6270efba60d1ee539ac5a36a524db98e912c51af654c965335f33a8f656bca3c34ccae9a87af9eaac6ac3f17d5f2a26637f7f5a25cb81fb615f38349d17f26b406c3ee7570377d7e75312fd6c5be38e1cbc5bd78179f8d897f092e6134b8449798c9d2b91fccbadefb159cde673059946a7449823e47f6d9c7fea32ca859283c96225912f549bdbfa4ec9e593fc6fdfa9c6df523d4af3d18a774e75d2fb9925e8ad0c8eefbbcfd525eaacbe5525f9a4b6b9c2edde56a6fcdd1e5165f98bd93244764f10773e445d68e5da55df4cbeab2b6c2cbe6b2bddc5d7655a7b697fde57039ba2fbd2c173633b1d8cde27fd5d684fde2fef27079e4b2a0adfd5add3f95256071f24d29c2faf27479eeb585d61bfb95a07ecd81e9d8a377f35545b3df7975c88ca6feec72bebc5c5ecdc4383afae58daf136d8235f75dbd7e8db92c7c3d96f5f196c5dd5333bebc5f3e2e9f97afcb777cbcf06a13d388e16578195dc66c869ddb6c66cd466c967db5ee7adbbf4c2ed3cb8ccba2f0bcc2fe5d16392f4096545373b5cdcf97f9657159f6eb90bdcdb2d8b85fd50accc08d8c83a7298f8a1fb4c620fca8d55a49b6b5519bc98ac9f9565bb56def1cc38bfaf99ecd8d336ef74cc7b8341e9b3146e6dcdef82cdeac9ddaadbddaaf83484b46e9ad0eeba88eeb84e5ca9fcce3796c6e9db008f4c9dd32590e755a67756e325990875bfd0aeaeff9cbcfb2287eaa2b6e5dd4a5f25557c68149c0bc0fb3dfa8978569716cc69eee2b6aa9cc422bfc8caa9a4590ec7f0d6b5beb7eb84347cdaf2c63af9cd73063f67faa22f6ebdeaff7d27875c746f9cbfc626d5cd6d7fa566bb55eafea35d36ca77c8af27a536fcdd8b9b23cdceb6318d6239bdec2eabb7a57efcb3d932515759e3fe695d8112074cc55efd44370523ae5b13e184cb3597e7f6fdbbc12cfda581f599b4ff57dfde0b6a1556d13b77eac9fea67e3549feb17a65b8bfab59f159cd728b02d1691ceeb37bfb1b7fe376fd994b220ca89acbdfb5abfd71ff56738a8bfeaef7a500fcba01e992ed3c27db17077aec3f29881cb324b63578feb493de5b2507ef20f7264f6a797a59ffb13f6ff0d9bfda7f5ac9ed70b9657b2fc8bc52e5b7b592f9d779bcdc98dda288de13f5a35f3ca1f8dd958c64363db47f6d9374e3f438693be6ed3fbb2c665ff34a2d0def09a9af1cb1ae0d074eb5be3357e1334a1f3d4444ddc244dcafae291e54977eeaec9ac2dfb158b429bbc299ab2a9b8bdd09ca8f42b763fcb42732397c5e4b364aa8cd2cc99c77a7369eaa6316377c3eefb7039352d0b8359d6e186c6aee99a6b738badd0b48a466b74fbc18c9b557aecc7c57c6fd64cdfc76c2c3efa5cbdd9345bebdcdcb9dbbe8283d53fac9c9b5ebfb3a4d935fbe6604d9a63736aee9b0726c363f3d43c3799bbeb6be64c2fe3e6dcbc34afcd9b948559c51f65a1d95ecaa2f1959bb5faa138cd7bf3c1a22ac7ff609e89d973bfa6686f9b4fe3e0dbcd57f31dbae167ad3483669828d60b7bde283359ae356bc66c961b46611f41369366dacc9ab971b296eeb6e1e3815566167d9b9ed3354b63efad5bb5555aa3355bcbe8ebd581396efb15c45d9f2b87ba71689dd66dbdd6ef63181e7719aadfaf09ff365752a5cfa4bdc2fdfa937a8bc76de03dc65d1b1afd4afdb658703fbbed6dba8d8c531bb7499b865ef5de666d9e9fdaa22ddbcad8370fed85595585fce4beaddba66ddbaebd5e5876dfded8bcf3ddd70ee4eabfefed5aaddf1de36baddeaeda755bb35f6dda6df0dede056f5ec89eb7734a63d7eedb437b6c4f52163f38fd41161bd97abff39945bc2c951e313ddbe5b9a2b7f7ed43fbc8b4f7686ffa9d05b5d53ef55adf326fdf9edb97f6d518861f4e5c44ed5bb269df59ccb3cf3b7bc9645ef5f949fbd17eb65fed773b6887eda865b3068b697aed123b19f67e906bf6b69db0acf8d44edb593b6751cb397875ed76d12e3bb59fdbeace38754a67746667c571922779af472c8e39fe4116e75759d84c99a94967770e93e6dab99d67192cd770d89cb063be56ef7c7b5b9f7d3753baa00bbba8da767197746997b1b0b8e8ca7e6dc8db75157bfea5abbbc6df756dd775d7eed6699ddeadfaac8e723b5ec95b326b687b8fe2fb4e65dce75db7ee36eeaedb76776c02d875fbe6397aef0eddb13b75f7dd43f7f8ab2cbfc563b40fdae2fbb87b59fabdb76ef7d43de7cfddb97be95e6bc738b9ae7de8ff1a4166c38eb3eddeba77964f9cba8feeb3fbeabe9d85fad80dba6137eac6d19d195b0b33f6b56ed24dbb5937ef16ddf2aa5e95ab71358d9dfbca7763f9bd1ce6d00ffa99fd6ad97bc7bada4cbe73b7bb322bb18ee1cadd5d5deffdea3109dfaffe35b886d7280fa302b66ffe1d1d13eb0b72bf196a7fdcef5de36b52b2d65d53ebe19ab119ef6c9dddcf7eb5f79ab3ff5a5ccb6bc5e29897ebe55a5bfeb5b9b6d7ee7acd27d7db55bb321d5533b30bdf8da69c5c57d7f57573dde6937efe655aa8f4750ce623a2be06c6f7638dd87c74ecfd38d515ade7de5aaa8171bcde5d77d7bdda3847b5edab2c5993353c07367f9c07f8afd7f89ca7ebe17a8cd953afa7eb3d3dddbf998b6641d1eef5e1fa787dba3e5fcfd797eb6bad3069deaeefd78febe7f5ebfa5d75d74139bc0eafa3eb987d26d7e975769d7b6bd60b8bcccccceb92dba2f5f327f2dd7d73c7fc1c27ebcc52c3a79b7263f955348c4c36f3b9aa6dbf33591cbebef31764b99937eb66df1cd6379ecb66877edf8bad140b2fb9b139d0b8f7b51b0b346f8152ddc25b748bd5db2db9a5b7ec96df8a68d025e15755df4a7377ab6e97f0e3c626c65b5bac6e9db1ef772df0fd16d6af1f5eafb0d86cc4246aee7236b3dcaeb7db4d4bc6d133cb2d44fefb87ddf3ffb52ce6e34dbfad6eeb86c5860d1b0d663515f3f8ecff6d8fc5eecc9fe593dbe6b6bdddd5a5fa62d7cae2b65386b7fdeda0d4ea58dd869f55773bde4eb7fbcbddede1f6787bba3ddfce51623f180fb71733643e7af24759983454afa4fbbfdede54f7f67efb48068a226ac97f7d7d3f2a6e9fb7afdbf76dc02b565f2cb35c58776c86d89a73162f6d6e43e3741bddc6b7c96d9abab759eadce6f1241ef77bf56f8bc80a5fa2eab6d4d4a8d394a85202f5ac199aa9599aadb1b16e5acdedade4e78fbbef3396c82759cc58f3345f0bb4508bf242d1d20ce3f287d3597fc25e1eb5584bb454cbfad981dd7b617e7a119385f624cdedad96f733a75668a5566917ad564325615ed0b65fe289b25322add15aadd3aedacdf84c1dd573979aa6e9da4a5b6b1b7ba16da99af0ebc8b03f2a8bb1ad7667dada9db653bba0b9bddbef2c7f37642dcfa1f8f22fc8926a7beda01db59376af3db008efce9cfa1f2c3bda71eb6451633568f92e43ed517bd29eb5b3f6a2bd46b935d2de8c85f61e4fb40f36269f2c216e94246ccb2767e999da97f6ad0d3436a6edeeefd98bf5dcee2c35f2b59136d6260a8bd955d72eed525db37111f562ef2fcbf2a84db59936d716da52578d7da8318f79673d9993b86e6fecb363518056b6bac26c79a71bbad92a9dab5bc64db77527327457c97596ee844e7fe622ce597e32d4033dd4233dd6133dedc7e0d74f98f5b2447e2f95bbd7333dcfebb2d20bf6fbfe0c84266b797c86ff2b3a16157aa957fa45aff5466ff5aedf11c3f2de39af8f322fa45ffb798faffbfaa6ebbe66817ed3355dd757fa5adfe85bfdcef850bff59dbe77c6d5413fe847fda4dfeb0ffaa3fe14bd07aece722db28dde4ef86e0bf3e78fe9e8e764adbfe8af4aa36ead86cdca34abf4f6eff075c43fbd8724c9f537fdbdb8ea1ffaa7fea57febcc07588affed6ed3ca56a3f7beea637afd3a561f4733895c33d687fa888dd0589fe8537da6cff585be5ca92b6565accc95e5eddd3c7ded778d38d5ca5e39b6e1eec90f0b0ff68b2cae7170dc95bbf2567e3c535f56415f310a4e2cdeea57df6a5a7bfb73b2048fab701505b355bc4a56e92a5be5ed78555807166b6efa5ccb3afe248bc9b28265dee5ceed8565b4b755b9aa5697555dcd568d3e5ab5b1c7f7c23129dcddaaeb76abab395e752c5bbbe3f66e626ef955166f7533e3b261f9d270a5b1f178e335567efeafaf2afd9571311f57fa6ab55a6bb362b8daacb6abbbcbc76ad75767d2a05f79b0b67d0ecf64796372ec983c0adfc570cff7819ef85efea3d8cf6bdcbbdf76e87ff8cd6abf3aac8ead1d7cb84edffa7e9e679aa6b63b6627bfcae2af4eab7b9643ad570fcdfbea919fce727f3a052c4f69fca971795a3dafceab176db67ad5ebd5dbea7df5b1fa8cbff26ef595f615a31fbbddf98749f7c177bc0f9d57f6795b7daf06d17e35147b2cfbbdbccd9339ee7739b58bd5a8d72e173b9358e3acdf65b1ceab717d67ec5693d574355bcd51c3b7708ec1fdf3314c92af16abe55a5d2b6b439badcdb5b5b6d7ceda5d7bc69e45cffb1f7bdefb489eaffb32097a7b62b3105fc7e3fba9f9beea7e36627e6318266b7f1dacc3c0091cbecb91452c6431bd17f85d967e7473dbd8d7efeb681dab77e20c2d9745f9b16be9cff8b1f03198af933c5d5bc1789daeb375be2ed6e5ba5a5fd6b5b5b437741601fbf7fbd5b30fbe57a25f6bb15a16fc34ceba757416dfb3e83e9ce9d77ecd807df6ebceefd6cc62bc50c8d2eeb411f366bfd90bd7d26374b7beadb53573e4b2fee5fed5793f628aba5eaf37ebedfa6ebd5befd787f5717d5adfaf1fd68feba790c5fdd69eef5ac1b8b04fbf9ef76a7e704b3e584bbedb9f5950bffba8f7e2eb7e97fcb1df83b63eaf5f02d736cc28effa73246c8e1feb193f73d2e7373edfafe4b23c69bb7e5dbf35cafa7dfdc1e617c8f2f7f78ffdf38ff3283f69566595d196e7f5e7fa6bfdbd1eac87eb11d335bea38c568b980e4db0afbf8fa6c6acc7cffc04c6b2dfadd7cbe90f7a7bea77569a43967505d5e0a69a713e6171d79d36d1f3f5b8f776eb49bfa3b61f93cb389f38de7aba9eade7eabdd8d32b674be7afc8f2d3d9621ecf798f6a11dcaf179774bdcc5f36ea46d9181bb37faead164ebf368979c230a77db5439cb4602336661ab91436d3dc39174ba1fd0a2caa7f6511e4ae0f0b36569fdfacc6cce59f8ce3c6c9271b77e36dfc4d607da94f56f35b9bfed2b8fc7eb6381a2a9ee2da55972acd26dc449b78936cd24db6c9f9aa0bcb6eac27ffdbf68bbc782effdf76ae6549552488eee733a6f615fdba7dbb6356a899203e5a6db51f3b4444f0c14b1489987f9faa8202a4bd37b457331113b9d010943a661645669d93b6d9e37b5a6207f5ce54d90a7b630ee6244ed8f3c2d4532060d9afca32ad349d280e4d481246103617866ae8b10a11c3b2b36c86248e1fe983506f36cb7bd7f59cde1344592e9dd23decc91c0e90c0115250a0014d680104cf80a691efb672cf7c667bc1191af13a6a6c8d2ed758790ea8a041fba8a546ca6681e23a2c67047dffd9b4a1130fb9e20cbad0833e2ce34747a706bc2c0e85fef98baee722bfd4f4404187dc51957668dcd0c2d0b660004318c12b8c61025378f3347fb13bb0acbe5df0f8ab3a31cdd0e01d3ee0136ee036e9c2ddb1ed7437f7e95459c13d7169c0bcfd003fe0117eb2bb700a4ff08c94def1b9eef5e9337dca1557dfc052a8ea8aefae6ed98c216b9d45ef4ffa485524aebeeaa181333471eeaa5edbb7f71bff47100423b4421517519a70a1686ff7106f632dbe471b97ebe0a027b3a4874ec8a276354cdffc603e255ca59dee228325a4b8c2354b719e8d29bbca113774bcb961e319c8f15c1f6327bd3884873ca043ee1bdcda7dce35430f7d0c30740718e10e636fed2f7ddd7f0cc2861b3aa1161991827b3cecfa8d66ec6112bce2115354f693204dfadb96d559cd6ccab25f967cd21655d61b3627a2d61336b0892d72a03dc20e53978ef868d8fa229f5faee75a7fe935c07eb745b764495b08ec7d0311d5f514356ca3bffd70224ff774bfb3f1822818bb5ad8461d3bd8c5de6e837df6fe0507fb088787258ef015c7d68bd0fa1a7cc79ef3f0a8623d21573237714a0f6bb636061dba66de58d0211dac1b76bfe293ef6039b59ad281736c393795d713791dceebf80ee712f96e3009ddd07544a5d179e13613e6e4967d435ca3ec245389a0cad56bfd58aad7bf7aee9fc122ff178e852391e3f3ba9c7d9399eff23a234758aeb7d96b869def6fe7fb0f468e60216ac18678a2378b9890bd31a42ee18c42f1d27b720dcf09969c1fb0909d7904e76ec356026184f0baafc89d66956e3da5fecbf6f6f369d67545d6b5c5d924df135a7ec542cb5e26e49a7cbfc201afa191da8093df3604f79408ae9ab0ad576031ca9ca3caca1635c83935653d22cfb448ce3bcf6adc752c32e62a9eb9443352aa19aaaae7e288acea1ab4729f2cb50e052bf5d4871cf952b02732ae47d9db635ea9689b453c57bc2062244752ad5f5e84c592fcc3e1ee4c949995795bc152fdbea830d827ffc84c20e9088f91d2fb395e4b665b520152c3422492ebf27dce3a1163b10a2cc60916c11710bad85b6ed69a7320cdc09db863ceee0a1533e20c1ccef6c814cd995eb334f9fc9ecf4b7ebda988b5c23b67b1108e04dff03d63da7fc32f8b9a5f4caeec2fc7c9c7e6f5bc5e154b795ce2e596e3679fca7dd222b624e3bc58134fe3a1e0bbcd199677fcb81c4b3d6a7ea7d6aeb0fb7e71ceb9a3f5738b7cbeda2ba7de3ba79caf57e52fff15fb1fcbbfd3fefcfbaf3ffe0193cc32fd</data>
+ </image>
+</images>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>klistbox.h</includehint>
+</includehints>
+</UI>
diff --git a/kioslave/media/mimetypes/Makefile.am b/kioslave/media/mimetypes/Makefile.am
new file mode 100644
index 000000000..25c718035
--- /dev/null
+++ b/kioslave/media/mimetypes/Makefile.am
@@ -0,0 +1,22 @@
+mimetypedir = $(kde_mimedir)/media
+
+mimetype_DATA = floppy_mounted.desktop floppy_unmounted.desktop \
+ floppy5_unmounted.desktop floppy5_mounted.desktop \
+ zip_mounted.desktop zip_unmounted.desktop \
+ hdd_mounted.desktop hdd_unmounted.desktop \
+ removable_mounted.desktop removable_unmounted.desktop \
+ cdrom_mounted.desktop cdrom_unmounted.desktop \
+ dvd_mounted.desktop dvd_unmounted.desktop \
+ cdwriter_mounted.desktop cdwriter_unmounted.desktop \
+ smb_mounted.desktop smb_unmounted.desktop \
+ nfs_mounted.desktop nfs_unmounted.desktop \
+ audiocd.desktop \
+ dvdvideo.desktop \
+ blankcd.desktop \
+ blankdvd.desktop \
+ svcd.desktop \
+ vcd.desktop\
+ gphoto2camera.desktop camera_mounted.desktop camera_unmounted.desktop
+
+
+EXTRA_DIST = $(mimetype_DATA)
diff --git a/kioslave/media/mimetypes/audiocd.desktop b/kioslave/media/mimetypes/audiocd.desktop
new file mode 100644
index 000000000..8b0e47e42
--- /dev/null
+++ b/kioslave/media/mimetypes/audiocd.desktop
@@ -0,0 +1,66 @@
+[Desktop Entry]
+Type=MimeType
+MimeType=media/audiocd
+Comment=Audio CD
+Comment[af]=Musiek CD
+Comment[ar]=قرص مدمج صوتي
+Comment[be]=Гукавы CD
+Comment[bg]=Аудио диск
+Comment[bn]=অডিও সিডি
+Comment[br]=CD klevet
+Comment[ca]=CD d'àudio
+Comment[cs]=Zvukové CD
+Comment[csb]=Aùdio CD
+Comment[da]=Lyd-cd
+Comment[el]=CD ήχου
+Comment[eo]=Muzikaj lumdiskoj
+Comment[fa]=دیسک فشردۀ صوتی
+Comment[fi]=CD-äänilevy
+Comment[fr]=CD audio
+Comment[fy]=Audio-Kompaktskiif
+Comment[ga]=Dlúthdhiosca Fuaime
+Comment[gl]=CD de audio
+Comment[he]=תקליטורי שמע
+Comment[hi]=ऑडियो सीडी
+Comment[hr]=Glazbeni CD
+Comment[hu]=Hang-CD
+Comment[is]=Hljóðdiskur
+Comment[it]=CD audio
+Comment[ja]=オーディオ CD
+Comment[kk]=Аудио CD
+Comment[km]=ស៊ីឌី​អូឌីយ៉ូ
+Comment[mk]=Аудио ЦД
+Comment[ms]=CD Audio
+Comment[nb]=Lyd-CD
+Comment[nds]=Audio-CD
+Comment[ne]=अडियो सीडी
+Comment[nl]=Audio-cd
+Comment[nn]=Lyd-CD
+Comment[pa]=ਆਡੀਓ CD
+Comment[pl]=Płyta CD Audio
+Comment[pt]=CD de áudio
+Comment[pt_BR]=CD de Áudio
+Comment[ro]=CD Audio
+Comment[ru]=Аудио CD
+Comment[rw]=CD y'Inyumvo
+Comment[se]=Jietna-CD
+Comment[sl]=Glasbeni CD
+Comment[sr]=Аудио CD
+Comment[sv]=Ljud-cd
+Comment[te]=ఆడియో సిడి
+Comment[tg]=Аудио CD
+Comment[th]=ซีดีเพลง
+Comment[tr]=Müzik CD'si
+Comment[tt]=Tawış CD
+Comment[uk]=Аудіо КД
+Comment[uz]=Audio kompakt-disk
+Comment[uz@cyrillic]=Аудио компакт-диск
+Comment[vi]=CD Nhạc
+Comment[wa]=Plake lazer CD odio
+Comment[zh_CN]=音频 CD
+Comment[zh_TW]=音樂 CD
+Icon=cdaudio_unmount
+
+X-KDE-AutoEmbed=true
+X-KDE-IsAlso=inode/directory
+
diff --git a/kioslave/media/mimetypes/blankcd.desktop b/kioslave/media/mimetypes/blankcd.desktop
new file mode 100644
index 000000000..723ade236
--- /dev/null
+++ b/kioslave/media/mimetypes/blankcd.desktop
@@ -0,0 +1,73 @@
+[Desktop Entry]
+Type=MimeType
+MimeType=media/blankcd
+Comment=Blank CD
+Comment[af]=Leë CD
+Comment[ar]=قرص مدمج فارغ
+Comment[be]=Пусты CD
+Comment[bg]=Празен диск
+Comment[bn]=ফাঁকা সিডি
+Comment[br]=Goullonderiñ ur CD
+Comment[bs]=Prazan CD
+Comment[ca]=CD en blanc
+Comment[cs]=Prázdné CD
+Comment[csb]=Czëstô CD
+Comment[da]=Blank cd
+Comment[de]=Leere CD
+Comment[el]=Κενό CD
+Comment[eo]=Malplena lumdisko
+Comment[es]=CD vacío
+Comment[et]=Tühi CD
+Comment[eu]=CD hutsik
+Comment[fa]=دیسک فشردۀ خام
+Comment[fi]=Tyhjä CD
+Comment[fr]=CD vierge
+Comment[fy]=Blanke Kompaktskiif
+Comment[ga]=Dlúthdhiosca Folamh
+Comment[gl]=CD valeiro
+Comment[he]=תקליטור ריק
+Comment[hi]=खाली सीडी
+Comment[hr]=Prazan CD
+Comment[hu]=Üres CD
+Comment[is]=Tómur CD
+Comment[it]=CD vergine
+Comment[ja]=空の CD
+Comment[ka]=სუფთა CD
+Comment[kk]=Таза CD
+Comment[km]=ស៊ីឌី​ទទេ
+Comment[lt]=Tuščias CD
+Comment[lv]=Tukšs CD
+Comment[mk]=Празно ЦД
+Comment[ms]=CD Kosong
+Comment[nb]=Tom CD
+Comment[nds]=Leddige CD
+Comment[ne]=खाली सीडी
+Comment[nl]=Lege cd
+Comment[nn]=Tom CD
+Comment[pa]=ਖਾਲੀ CD
+Comment[pl]=Pusta płyta CD
+Comment[pt]=CD vazio
+Comment[pt_BR]=CD virgem
+Comment[ro]=CD gol
+Comment[ru]=Чистый CD
+Comment[rw]=CD Itanditseho
+Comment[se]=Guorus CD
+Comment[sk]=Čisté CD
+Comment[sl]=Prazen CD
+Comment[sr]=Празан CD
+Comment[sr@Latn]=Prazan CD
+Comment[sv]=Tom cd
+Comment[ta]=காலி குறுந்தகடு
+Comment[te]=ఖాళి సిడి
+Comment[th]=ซีดีเปล่า
+Comment[tr]=Boş CD
+Comment[tt]=Buş CD
+Comment[uk]=Чистий КД
+Comment[uz]=Boʻsh kompakt-disk
+Comment[uz@cyrillic]=Бўш компакт-диск
+Comment[vi]=CD trống
+Comment[wa]=Plake lazer CD sins rén dzo
+Comment[zh_CN]=空 CD
+Comment[zh_TW]=空白 CD
+Icon=cdwriter_unmount
+
diff --git a/kioslave/media/mimetypes/blankdvd.desktop b/kioslave/media/mimetypes/blankdvd.desktop
new file mode 100644
index 000000000..f5f06c9bc
--- /dev/null
+++ b/kioslave/media/mimetypes/blankdvd.desktop
@@ -0,0 +1,73 @@
+[Desktop Entry]
+Type=MimeType
+MimeType=media/blankdvd
+Comment=Blank DVD
+Comment[af]=Leë DVD
+Comment[ar]=قرص رقمي مرئي فارغ
+Comment[be]=Пусты DVD
+Comment[bg]=Празен DVD диск
+Comment[bn]=ফাঁকা ডিভিডি
+Comment[br]=Goullonderiñ un DVD
+Comment[bs]=Prazan DVD
+Comment[ca]=DVD en blanc
+Comment[cs]=Prázdné DVD
+Comment[csb]=Czëstô DVD
+Comment[da]=Blank dvd
+Comment[de]=Leere DVD
+Comment[el]=Κενό DVD
+Comment[eo]=Malplena DVD
+Comment[es]=DVD vacío
+Comment[et]=Tühi DVD
+Comment[eu]=DVD hutsik
+Comment[fa]=DVD خام
+Comment[fi]=Tyhjä DVD-levy
+Comment[fr]=DVD vierge
+Comment[fy]=Blanke Dûbelskiif
+Comment[ga]=DVD Folamh
+Comment[gl]=DVD valeiro
+Comment[he]=תקליטור DVD ריק
+Comment[hi]=खाली डीवीडी
+Comment[hr]=Prazan DVD
+Comment[hu]=Üres DVD
+Comment[is]=Tómur DVD
+Comment[it]=DVD vergine
+Comment[ja]=空の DVD
+Comment[ka]=სუფთა DVD
+Comment[kk]=Таза DVD
+Comment[km]=ឌីវីឌី​ទទេ
+Comment[lt]=Tuščias DVD
+Comment[lv]=Tukšs DVD
+Comment[mk]=Празно DVD
+Comment[ms]=DVD Kosong
+Comment[nb]=Tom DVD
+Comment[nds]=Leddige DVD
+Comment[ne]=खाली डी भी डी
+Comment[nl]=Lege dvd
+Comment[nn]=Tom DVD
+Comment[pa]=ਖਾਲੀ DVD
+Comment[pl]=Pusta płyta DVD
+Comment[pt]=DVD vazio
+Comment[pt_BR]=DVD virgem
+Comment[ro]=DVD gol
+Comment[ru]=Чистый DVD
+Comment[rw]=DVD Itanditseho
+Comment[se]=Guorus DVD
+Comment[sk]=Čisté DVD
+Comment[sl]=Prazen DVD
+Comment[sr]=Празан DVD
+Comment[sr@Latn]=Prazan DVD
+Comment[sv]=Tom dvd
+Comment[ta]=காலி டிவிடி
+Comment[te]=ఖాళి డివిడి
+Comment[th]=ดีวีดีเปล่า
+Comment[tr]=Boş DVD
+Comment[tt]=Buş DVD
+Comment[uk]=Чистий DVD
+Comment[uz]=Boʻsh DVD
+Comment[uz@cyrillic]=Бўш DVD
+Comment[vi]=DVD trống
+Comment[wa]=Plake lazer DVD sins rén dzo
+Comment[zh_CN]=空 DVD
+Comment[zh_TW]=空白 DVD
+Icon=cdwriter_unmount
+
diff --git a/kioslave/media/mimetypes/camera_mounted.desktop b/kioslave/media/mimetypes/camera_mounted.desktop
new file mode 100644
index 000000000..e08488829
--- /dev/null
+++ b/kioslave/media/mimetypes/camera_mounted.desktop
@@ -0,0 +1,69 @@
+[Desktop Entry]
+Type=MimeType
+MimeType=media/camera_mounted
+Comment=Mounted Camera
+Comment[af]=Gekoppelde Kamera
+Comment[ar]=كاميرا مركبة
+Comment[be]=Прымацаваная камера
+Comment[bg]=Монтиран фотоапарат
+Comment[bn]=মাউন্ট করা ক্যামেরা
+Comment[br]=Kamera marc'het
+Comment[bs]=Priključena kamera
+Comment[ca]=Càmera muntada
+Comment[cs]=Připojená kamera
+Comment[csb]=Zamòntowónô òdjimkòwô kamera
+Comment[da]=Monteret kamera
+Comment[de]=Eingebundene Kamera
+Comment[el]=Προσαρτημένη κάμερα
+Comment[eo]=Surmetita Kamero
+Comment[es]=Cámara montada
+Comment[et]=Ühendatud kaamera
+Comment[eu]=Kamara muntatuta
+Comment[fa]=دوربین سوارشده
+Comment[fi]=Liitetty kamera
+Comment[fr]=Appareil photo monté
+Comment[fy]=Oankeppele kamera
+Comment[ga]=Ceamara Feistithe
+Comment[gl]=Cámara Montada
+Comment[he]=מצלמה מחוברת
+Comment[hr]=Pristupljena kamera
+Comment[hu]=Csatlakoztatott fényképezőgép
+Comment[is]=Tengd myndavél
+Comment[it]=Macchina fotografica montata
+Comment[ja]=マウントされたメディア
+Comment[ka]=მონტირებული კამერა
+Comment[kk]=Тіркеген фотокамера
+Comment[km]=ម៉ាស៊ីនថត​ដែល​បានម៉ោន
+Comment[lt]=Sumontuotas fotoaparatas
+Comment[mk]=Монтирана камера
+Comment[nb]=Montert kamera
+Comment[nds]=Inhangt Kamera
+Comment[ne]=माउन्ट गरिएको क्यामेरा
+Comment[nl]=Aangekoppelde camera
+Comment[nn]=Montert kamera
+Comment[pa]=ਮਾਊਂਟ ਹੋਇਆ ਕੈਮਰਾ
+Comment[pl]=Zamontowany aparat fotograficzny
+Comment[pt]=Câmara Montada
+Comment[pt_BR]=Câmera montada
+Comment[ro]=Aparat foto montat
+Comment[ru]=Подключённая камера
+Comment[se]=Čatnon govvenapperáhtta
+Comment[sk]=Pripojený digitálny fotoaparát
+Comment[sl]=Priklopljen fotoaparat
+Comment[sr]=Монтирана камера
+Comment[sr@Latn]=Montirana kamera
+Comment[sv]=Monterad kamera
+Comment[th]=กล้องดิจิตอลที่เมานท์แล้ว
+Comment[tr]=Bağlı Kamera
+Comment[uk]=Приєднана камера
+Comment[uz]=Ulangan fotoaparat
+Comment[uz@cyrillic]=Уланган фотоапарат
+Comment[vi]=Máy chụp ảnh số đã kết nối
+Comment[wa]=Montêye camera
+Comment[zh_CN]=挂载的相机
+Comment[zh_TW]=掛載的照相機
+Icon=camera_mount
+
+X-KDE-AutoEmbed=true
+X-KDE-IsAlso=inode/directory
+
diff --git a/kioslave/media/mimetypes/camera_unmounted.desktop b/kioslave/media/mimetypes/camera_unmounted.desktop
new file mode 100644
index 000000000..4a4d2ee6f
--- /dev/null
+++ b/kioslave/media/mimetypes/camera_unmounted.desktop
@@ -0,0 +1,69 @@
+[Desktop Entry]
+Type=MimeType
+MimeType=media/camera_unmounted
+Comment=Unmounted Camera
+Comment[af]=Ontkoppelde Kamera
+Comment[ar]=كاميرا غير مركبة
+Comment[be]=Адмацаваная камера
+Comment[bg]=Демонтиран фотоапарат
+Comment[bn]=আনমাউন্ট করা ক্যামেরা
+Comment[br]=DVD-ROM divarc'het
+Comment[bs]=Otkopčana kamera
+Comment[ca]=Càmera desmuntada
+Comment[cs]=Odpojená kamera
+Comment[csb]=Òdmòntowónô òdjimkòwô kamera
+Comment[da]=Afmonteret kamera
+Comment[de]=Nicht eingebundene Kamera
+Comment[el]=Μη προσαρτημένη κάμερα
+Comment[eo]=Demetita Kamero
+Comment[es]=Cámara desmontada
+Comment[et]=Lahutatud kaamera
+Comment[eu]=Kamara desmuntatua
+Comment[fa]=دوربین پیاده‌شده
+Comment[fi]=Irrotettu kamera
+Comment[fr]=Appareil photo non monté
+Comment[fy]=Ofkeppele kamera
+Comment[ga]=Ceamara Neamhfheistithe
+Comment[gl]=Cámara non Montada
+Comment[he]=מצלמה מנותקת
+Comment[hr]=Nepristupljena kamera
+Comment[hu]=Leválasztott fényképezőgép
+Comment[is]=Aftengd myndavél
+Comment[it]=Macchina fotografica non montata
+Comment[ja]=マウントされていないメディア
+Comment[ka]=დემონტირებული კამერა
+Comment[kk]=Тіркеуден шығарылған фотокамера
+Comment[km]=ម៉ាស៊ីន​ថត​ដែលបាន​អាន់​ម៉ោន
+Comment[lt]=Išmontuotas fotoaparatas
+Comment[mk]=Одмонтирана камера
+Comment[nb]=Avmontert kamera
+Comment[nds]=Afhangt Kamera
+Comment[ne]=अनमाउन्ट गरिएको क्यामेरा
+Comment[nl]=Afgekoppelde camera
+Comment[nn]=Avmontert kamera
+Comment[pa]=ਅਨਮਾਊਟ ਕੀਤਾ ਕੈਮਰਾ
+Comment[pl]=Odmontowany aparat fotograficzny
+Comment[pt]=Câmara Desmontada
+Comment[pt_BR]=Câmera desmontada
+Comment[ro]=Aparat foto nemontat
+Comment[ru]=Неподключённая камера
+Comment[se]=Gálgajuvvon govvenapperáhtta
+Comment[sk]=Odpojený digitálny fotoaparát
+Comment[sl]=Odklopljen fotoaparat
+Comment[sr]=Демонтирана камера
+Comment[sr@Latn]=Demontirana kamera
+Comment[sv]=Avmonterad kamera
+Comment[th]=กล้องดิจิตอลที่ไม่ได้เมานท์
+Comment[tr]=Ayrılmış Kamera
+Comment[uk]=Роз'єднана камера
+Comment[uz]=Ulanmagan fotoaparat
+Comment[uz@cyrillic]=Уланмаган фотоапарат
+Comment[vi]=Máy chụp ảnh số đã gỡ ra
+Comment[wa]=Dismontêye camera
+Comment[zh_CN]=未挂载的相机
+Comment[zh_TW]=未掛載的照相機
+Icon=camera_unmount
+
+X-KDE-AutoEmbed=true
+X-KDE-IsAlso=inode/directory
+
diff --git a/kioslave/media/mimetypes/cdrom_mounted.desktop b/kioslave/media/mimetypes/cdrom_mounted.desktop
new file mode 100644
index 000000000..18119ee32
--- /dev/null
+++ b/kioslave/media/mimetypes/cdrom_mounted.desktop
@@ -0,0 +1,85 @@
+[Desktop Entry]
+Icon=cdrom_mount
+Type=MimeType
+MimeType=media/cdrom_mounted
+Comment=Mounted CD-ROM
+Comment[af]=Gekoppelde CD-ROM
+Comment[ar]=قرص مدمج مركب
+Comment[az]=Bağlanmış CD-ROM
+Comment[be]=Прымацаваны CD-ROM
+Comment[bg]=Монтиран CD-ROM
+Comment[bn]=মাউন্ট করা সিডি-রম
+Comment[br]=CD-ROM marc'het
+Comment[bs]=Montiran CD-ROM
+Comment[ca]=CD-ROM muntat
+Comment[cs]=Připojená CDROM
+Comment[csb]=Zamòntowóny nëk CD
+Comment[cy]=CD-ROM wedi ei osod
+Comment[da]=Monteret cd-rom
+Comment[de]=Eingebundene CD-ROM
+Comment[el]=Προσαρτημένο CD-ROM
+Comment[eo]=Surmetita nurlegebla LD
+Comment[es]=CD-ROM montado
+Comment[et]=Ühendatud CD-ROM
+Comment[eu]=CD-ROM muntatua
+Comment[fa]=CD-ROM سوارشده
+Comment[fi]=Liitetty CD-ROM
+Comment[fr]=CD-ROM monté
+Comment[fy]=Oankeppele Kompaktskiif
+Comment[ga]=CD-ROM feistithe
+Comment[gl]=CD-ROM Montado
+Comment[he]=תקליטור מחובר
+Comment[hi]=माउन्टेड सीडी-रोम
+Comment[hr]=Pristupljeni CD-ROM
+Comment[hu]=Csatlakoztatott CD-ROM
+Comment[is]=Tengt geisladrif
+Comment[it]=CD-ROM montato
+Comment[ja]=マウントされた CD-ROM
+Comment[ka]=მონტირებული CD-ROM
+Comment[kk]=Тіркеген CD-ROM
+Comment[km]=CD-ROM បាន​រៀបចំ
+Comment[lo]=ຈໍພາບ
+Comment[lt]=Sumontuotas CD-ROM
+Comment[lv]=Piemontēts CD-ROM
+Comment[mk]=Монтиран ЦДРОМ
+Comment[mn]=Залгагдсан КД-ROM
+Comment[ms]=CD-ROM Terlekap
+Comment[mt]=CDROM immontat
+Comment[nb]=Montert CD-plate
+Comment[nds]=Inhangt CD-ROM
+Comment[ne]=माउन्ट गरिएको सीडी-रोम
+Comment[nl]=Aangekoppelde cd-romschijf
+Comment[nn]=Montert CD-ROM
+Comment[nso]=CD-ROM yeo e Nameleditswego
+Comment[pa]=ਮਾਊਟ ਕੀਤੀ CD-ROM
+Comment[pl]=Zamontowany CD-ROM
+Comment[pt]=CD-ROM montado
+Comment[pt_BR]=CD-ROM Montado
+Comment[ro]=CD-ROM montat
+Comment[ru]=Смонтированный CD
+Comment[rw]=CD-ROM Yashyizwemo
+Comment[se]=Čatnon CD-ROM
+Comment[sk]=Pripojený CD-ROM
+Comment[sl]=Priklopljen CD-ROM
+Comment[sr]=Монитран CD-ROM
+Comment[sr@Latn]=Monitran CD-ROM
+Comment[sv]=Monterad cd-rom
+Comment[ta]=ஏற்றப்பட்ட சிடிராம்
+Comment[tg]=Монтаж шудаи CD-ROM
+Comment[th]=ซีดีรอมที่เม้านท์แล้ว
+Comment[tr]=Bağlı CD-ROM
+Comment[tt]=Totaşqan CD-ROM
+Comment[uk]=Змонтований КД
+Comment[uz]=Ulangan kompakt-disk
+Comment[uz@cyrillic]=Уланган компакт-диск
+Comment[ven]=CD-ROM yo gonyiswaho
+Comment[vi]=Ổ CD ROM đã kết nối
+Comment[wa]=Plake lazer CD montêye
+Comment[xh]=CD-ROM Enyusiweyo
+Comment[zh_CN]=挂载的 CD-ROM
+Comment[zh_TW]=已掛載的 CD-ROM
+Comment[zu]=I-CD-ROM eyenyusiwe
+Patterns=
+
+X-KDE-AutoEmbed=true
+X-KDE-IsAlso=inode/directory
diff --git a/kioslave/media/mimetypes/cdrom_unmounted.desktop b/kioslave/media/mimetypes/cdrom_unmounted.desktop
new file mode 100644
index 000000000..6107bd32f
--- /dev/null
+++ b/kioslave/media/mimetypes/cdrom_unmounted.desktop
@@ -0,0 +1,86 @@
+[Desktop Entry]
+Icon=cdrom_unmount
+Type=MimeType
+MimeType=media/cdrom_unmounted
+Comment=Unmounted CD-ROM
+Comment[af]=Ontkoppel CD-ROM
+Comment[ar]=قرص مدمج غير محمّل
+Comment[az]=Ayrılmış CD-ROM
+Comment[be]=Адмацаваны CD-ROM
+Comment[bg]=Демонтиран CD-ROM
+Comment[bn]=আনমাউন্ট করা সিডি-রম
+Comment[br]=CD-ROM divountet
+Comment[bs]=Demontiran CD-ROM
+Comment[ca]=CD-ROM desmuntat
+Comment[cs]=Odpojená CDROM
+Comment[csb]=Òdmòntowóny nëk CD
+Comment[cy]=CD-ROM wedi'i ddadosod
+Comment[da]=Afmonteret cd-rom
+Comment[de]=Nicht eingebundene CD-ROM
+Comment[el]=Αποπροσαρτημένο CD-ROM
+Comment[eo]=Demetita nurlegebla LD
+Comment[es]=CD-ROM desmontado
+Comment[et]=Lahutatud CD-ROM
+Comment[eu]=CD-ROM desmuntatua
+Comment[fa]=CD-ROM پیاده‌شده
+Comment[fi]=Irrotettu CD-ROM
+Comment[fr]=CD-ROM non monté
+Comment[fy]=Ofkeppele Kompaktskiif
+Comment[ga]=CD-ROM neamhfheistithe
+Comment[gl]=CD-ROM Non Montado
+Comment[he]=תקליטור מנותק
+Comment[hi]=अनमाउन्टेड सीडी-रोम
+Comment[hr]=Nepristupljeni CD-ROM
+Comment[hsb]=Njemontowany CDnik
+Comment[hu]=Leválasztott CD-ROM
+Comment[is]=Aftengt geisladrif
+Comment[it]=CD-ROM smontato
+Comment[ja]=マウントされていない CD-ROM
+Comment[ka]=დემონტირებული CD-ROM
+Comment[kk]=Тіркеуден шығарған CD-ROM
+Comment[km]=CD-ROM មិន​បាន​រៀបចំ
+Comment[lo]=ຫັງກາລີ
+Comment[lt]=Išmontuotas CD-ROM
+Comment[lv]=Nomontēts CD-ROM
+Comment[mk]=Одмонтиран ЦДРОМ
+Comment[mn]=Салгаатай КД-ROM
+Comment[ms]=CD-ROM Nyahlekap
+Comment[mt]=CDROM mhux immontat
+Comment[nb]=Avmontert CD-plate
+Comment[nds]=Afhangt CD-ROM
+Comment[ne]=अनमाउन्ट गरिएको सीडी-रोम
+Comment[nl]=Afgekoppelde cd-romschijf
+Comment[nn]=Avmontert CD-ROM
+Comment[nso]=CD-ROM yeo e Theositswego
+Comment[pa]=ਅਨਮਾਊਟ ਕੀਤੀ CD-ROM
+Comment[pl]=Odmontowany CD-ROM
+Comment[pt]=CD-ROM desmontado
+Comment[pt_BR]=CD-ROM Desmontado
+Comment[ro]=CD-ROM nemontat
+Comment[ru]=Отмонтированный CD
+Comment[rw]=CD-ROM Yakuwemo
+Comment[se]=Gálgajuvvon CD-ROM
+Comment[sk]=Nepripojený CD-ROM
+Comment[sl]=Odklopljen CD-ROM
+Comment[sr]=Демонтиран CD-ROM
+Comment[sr@Latn]=Demontiran CD-ROM
+Comment[sv]=Avmonterad cd-rom
+Comment[ta]=வெளியேற்றிய குறுந்தகடு
+Comment[tg]=Ҷудо шудаи CD-ROM
+Comment[th]=ซีดีรอมที่ไม่ได้เม้านท์
+Comment[tr]=Ayrılmış CD-ROM
+Comment[tt]=Totaşmağan CD-ROM
+Comment[uk]=Демонтований КД
+Comment[uz]=Ulanmagan kompakt-disk
+Comment[uz@cyrillic]=Уланмаган компакт-диск
+Comment[ven]=CD-ROM i songo gonyiswaho
+Comment[vi]=Ổ CD-ROM đã gỡ ra
+Comment[wa]=Plake lazer CD dismontêye
+Comment[xh]=CD-ROM Enganyuswanga
+Comment[zh_CN]=未挂载的 CD-ROM
+Comment[zh_TW]=未掛載的 CD-ROM
+Comment[zu]=I-CD-ROM eyehlisiwe
+Patterns=
+
+X-KDE-AutoEmbed=true
+X-KDE-IsAlso=inode/directory
diff --git a/kioslave/media/mimetypes/cdwriter_mounted.desktop b/kioslave/media/mimetypes/cdwriter_mounted.desktop
new file mode 100644
index 000000000..110e8f0a5
--- /dev/null
+++ b/kioslave/media/mimetypes/cdwriter_mounted.desktop
@@ -0,0 +1,86 @@
+[Desktop Entry]
+Icon=cdwriter_mount
+Type=MimeType
+MimeType=media/cdwriter_mounted
+Comment=Mounted CD Writer
+Comment[af]=Gekoppelde Cd Skrywer
+Comment[ar]=ناسخ أقراص محمّل
+Comment[az]=Bağlanmış CD Yazıcı
+Comment[be]=Прымацаваны запісвальнік CD
+Comment[bg]=Монтиран компактдиск
+Comment[bn]=মাউন্ট করা সিডি-রাইটার
+Comment[br]=Engraver CD marc'het
+Comment[bs]=Montiran CD pisač
+Comment[ca]=CD Writer muntat
+Comment[cs]=Připojená vypalovačka CD
+Comment[csb]=Zamòntowóny wëpôlôrz CD
+Comment[cy]=Ysgrifennwr CD wedi'i osod
+Comment[da]=Monteret cd-skriver
+Comment[de]=Eingebundener CD-Brenner
+Comment[el]=Προσαρτημένο CD Writer
+Comment[eo]=Surmetita skribebla LD
+Comment[es]=Escritor de CDs montado
+Comment[et]=Ühendatud CD kirjutaja
+Comment[eu]=CD erretzaile muntatua
+Comment[fa]=CD Writer سوارشده
+Comment[fi]=Liitetty CD-kirjoitin
+Comment[fr]=Graveur de CD monté
+Comment[fy]=Oankeppele Kompaktskiif
+Comment[ga]=Scríbhneoir Feistithe CDanna
+Comment[gl]=Grabadora de CD Montada
+Comment[he]=צורב מחובר
+Comment[hi]=माउन्टेड सीडी-राइटर
+Comment[hr]=Pristupljeni CD snimač
+Comment[hsb]=Montowany CD-palak
+Comment[hu]=Csatlakoztatott CD-író
+Comment[is]=Tengdur geislaskrifari
+Comment[it]=Masterizzatore montato
+Comment[ja]=マウントされている CD ライター
+Comment[ka]=მონტირებული CD Writer
+Comment[kk]=Тіркеген CD Writer
+Comment[km]=ឧបករណ៍​សរសេរ​ស៊ីឌី​បាន​រៀបចំ
+Comment[lo]= ຈໍພາບ
+Comment[lt]=Sumontuotas CD rašymo įrenginys
+Comment[lv]=Piemontēts CD rakstītājs
+Comment[mk]=Монтиран ЦД-снимач
+Comment[mn]=Залгагдсан КД-шарагч
+Comment[ms]=Penulis CD Terlekap
+Comment[mt]=CDWriter immontat
+Comment[nb]=Montert CD-brenner
+Comment[nds]=Inhangt CD-Brenner
+Comment[ne]=माउन्ट गरिएको सीडी राइटर
+Comment[nl]=Aangekoppelde cd-writer
+Comment[nn]=Montert CD-brennar
+Comment[nso]=Sengwadi sa CD seo se Nameleditswego
+Comment[pa]=ਮਾਊਟ CD ਰਾਇਟਰ
+Comment[pl]=Zamontowana nagrywarka CD
+Comment[pt]=Gravador de CDs montado
+Comment[pt_BR]=Gravador de CD Montado
+Comment[ro]=CD Writer montat
+Comment[ru]=Смонтированный CD (с возможностью записи)
+Comment[rw]=Mwandika CD Yashyizwemo
+Comment[se]=Čatnon CD-čálli
+Comment[sk]=Pripojená napaľovacia mechanika CD
+Comment[sl]=Priklopljen zapisovalnik CD-jev
+Comment[sr]=Монтиран CD резач
+Comment[sr@Latn]=Montiran CD rezač
+Comment[sv]=Monterad cd-brännare
+Comment[ta]=ஏற்றப்பட்ட குறுந்தகடு எழுதி
+Comment[tg]=Монтажшудаи CD Writer
+Comment[th]=เครื่องเขียนซีดีที่เม้านท์แล้ว
+Comment[tr]=Bağlı CD Yazıcı
+Comment[tt]=Totaşqan CD Yazdırğıç
+Comment[uk]=Змонтований гравер КД
+Comment[uz]=Ulangan kompakt-disk yozuvchi
+Comment[uz@cyrillic]=Уланган компакт-диск ёзувчи
+Comment[ven]=Tshinwali tsha CD tsho gonyiswaho
+Comment[vi]=Ổ ghi CD đã kết nối
+Comment[wa]=Plake lazer CD sol broûleu montêye
+Comment[xh]=CD Writer Enyusiweyo
+Comment[zh_CN]=挂载的刻录机
+Comment[zh_TW]=已掛載的 CD Writer
+Comment[zu]=I-CD-Writer eyenyusiwe
+Patterns=
+
+X-KDE-AutoEmbed=true
+X-KDE-IsAlso=inode/directory
diff --git a/kioslave/media/mimetypes/cdwriter_unmounted.desktop b/kioslave/media/mimetypes/cdwriter_unmounted.desktop
new file mode 100644
index 000000000..7e2ea5933
--- /dev/null
+++ b/kioslave/media/mimetypes/cdwriter_unmounted.desktop
@@ -0,0 +1,86 @@
+[Desktop Entry]
+Icon=cdwriter_unmount
+Type=MimeType
+MimeType=media/cdwriter_unmounted
+Comment=Unmounted CD Writer
+Comment[af]=Ontkoppelde CD Skrywer
+Comment[ar]=ناسخ أقراص غير محمّل
+Comment[az]=Ayrılmış CD Yazıcı
+Comment[be]=Адмацаваны запісвальнік CD
+Comment[bg]=Демонтиран компактдиск
+Comment[bn]=আনমাউন্ট করা সিডি-রাইটার
+Comment[br]=Engraver CD divarc'het
+Comment[bs]=Demontiran CD pisač
+Comment[ca]=CD Writer desmuntat
+Comment[cs]=Odpojená vypalovačka CD
+Comment[csb]=Òdmòntowóny wëpôlôrz CD
+Comment[cy]=Ysgrifennwr CD wedi'i ddadosod
+Comment[da]=Afmonteret cd-skriver
+Comment[de]=Nicht eingebundener CD-Brenner
+Comment[el]=Αποπροσαρτημένο CD Writer
+Comment[eo]=Demetita skribebla LD
+Comment[es]=Escritor de CDs desmontado
+Comment[et]=Lahutatud CD kirjutaja
+Comment[eu]=CD erretzaile desmuntatua
+Comment[fa]=CD Writer پیاده‌شده
+Comment[fi]=Irrotettu CD-kirjoitin
+Comment[fr]=Graveur de CD non monté
+Comment[fy]=Ofkeppele Kompaktskiif
+Comment[ga]=Scríbhneoir Neamhfheistithe CDanna
+Comment[gl]=Grabadora de CD Non Montada
+Comment[he]=צורב מנותק
+Comment[hi]=अनमाउन्टेड सीडी-राइटर
+Comment[hr]=Nepristupljeni CD snimač
+Comment[hsb]=Njemontowany CD-palak
+Comment[hu]=Leválasztott CD-író
+Comment[is]=Aftengdur geislaskrifari
+Comment[it]=Masterizzatore smontato
+Comment[ja]=マウントされていない CD ライター
+Comment[ka]=დემონტირებული CD Writer
+Comment[kk]=Ажыратылған CD Writer
+Comment[km]=ឧបករណ៍​សរសេរ​ស៊ីឌី​មិន​បាន​រៀបចំ
+Comment[lo]= ຫັງກາລີ
+Comment[lt]=Išmontuotas CD rašymo įrenginys
+Comment[lv]=Nomontēts CD rakstītājs
+Comment[mk]=Одмонтиран ЦД-снимач
+Comment[mn]=Салгагдсан КД-шарагч
+Comment[ms]=Penulis CD Nyahlekap
+Comment[mt]=CDWriter mhux immontat
+Comment[nb]=Avmontert CD-brenner
+Comment[nds]=Afhangt CD-Brenner
+Comment[ne]=अनमाउन्ट गरिएको सीडी राइटर
+Comment[nl]=Afgekoppelde cd-writer
+Comment[nn]=Avmontert CD-brennar
+Comment[nso]=Sengwadi sa CD seo se Theositswego
+Comment[pa]=ਅਨਮਾਊਟ CD ਰਾਇਟਰ
+Comment[pl]=Odmontowana nagrywarka CD
+Comment[pt]=Gravador de CDs desmontado
+Comment[pt_BR]=Gravador de CD Desmontado
+Comment[ro]=CD Writer nemontat
+Comment[ru]=Отмонтированный CD (с возможностью записи)
+Comment[rw]=Mwandika CD Yakuwemo
+Comment[se]=Gálgajuvvon CD-čálli
+Comment[sk]=Nepripojená napaľovacia mechanika CD
+Comment[sl]=Odklopljen zapisovalnik CD-jev
+Comment[sr]=Демонтиран CD резач
+Comment[sr@Latn]=Demontiran CD rezač
+Comment[sv]=Avmonterad cd-brännare
+Comment[ta]=வெளியேற்றிய குறுந்தகடு எழுதி
+Comment[tg]=Ҷудо шудаи CD Writer
+Comment[th]=เครื่องเขียนซีดีที่ไม่ได้กเม้านท์
+Comment[tr]=Ayrılmış CD Yazıcı
+Comment[tt]=Totaşmağan CD Yazdırğıç
+Comment[uk]=Демонтований гравер КД
+Comment[uz]=Ulanmagan kompakt-disk yozuvchi
+Comment[uz@cyrillic]=Уланмаган компакт-диск ёзувчи
+Comment[ven]=Tshinwali tsha CD tshi songo gonyiswaho
+Comment[vi]=Ổ ghi CD đã gỡ ra
+Comment[wa]=Plake lazer CD sol broûleu dismontêye
+Comment[xh]=CD Writer Enganyuswanga
+Comment[zh_CN]=未挂载的刻录机
+Comment[zh_TW]=未掛載的 CD Writer
+Comment[zu]=I-CD-Writer eyehlisiwe
+Patterns=
+
+X-KDE-AutoEmbed=true
+X-KDE-IsAlso=inode/directory
diff --git a/kioslave/media/mimetypes/dvd_mounted.desktop b/kioslave/media/mimetypes/dvd_mounted.desktop
new file mode 100644
index 000000000..2d9e0b512
--- /dev/null
+++ b/kioslave/media/mimetypes/dvd_mounted.desktop
@@ -0,0 +1,81 @@
+[Desktop Entry]
+Icon=dvd_mount
+Type=MimeType
+MimeType=media/dvd_mounted
+Comment=Mounted DVD
+Comment[af]=Gekoppelde DVD
+Comment[ar]=DVD محمّل
+Comment[az]=Bağlanmış DVD
+Comment[be]=Прымацаваны DVD
+Comment[bg]=Монтиран DVD диск
+Comment[bn]=মাউন্ট করা ডিভিডি
+Comment[br]=DVD marc'het
+Comment[bs]=Montiran DVD
+Comment[ca]=DVD muntat
+Comment[cs]=Připojené DVD
+Comment[csb]=Zamòntowóny nëk DVD
+Comment[cy]=DVD wedi'i osod
+Comment[da]=Monteret dvd
+Comment[de]=Eingebundene DVD
+Comment[el]=Προσαρτημένο DVD
+Comment[eo]=Surmetita DVD
+Comment[es]=DVD montado
+Comment[et]=Ühendatud DVD
+Comment[eu]=DVD muntatua
+Comment[fa]=DVD سوارشده
+Comment[fi]=Liitetty DVD-levy
+Comment[fr]=DVD-ROM monté(s)
+Comment[fy]=Oankeppele Dûbelskiif
+Comment[ga]=DVD feistithe
+Comment[gl]=DVD Montado
+Comment[he]=כונן DVD מחובר
+Comment[hi]=माउन्टेड डीवीडी
+Comment[hr]=Pristupljeni DVD
+Comment[hu]=Csatlakoztatott DVD
+Comment[is]=Tengt DVD
+Comment[it]=DVD montato
+Comment[ja]=マウントされた DVD
+Comment[ka]=მონტირებული DVD
+Comment[kk]=Тіркеген DVD
+Comment[km]=ឌីវីឌី​ដែល​បាន​រៀបចំ
+Comment[lo]=ຈໍພາບ
+Comment[lt]=Sumontuotas DVD
+Comment[lv]=Piemontēts DVD
+Comment[mk]=Монтиран DVD
+Comment[mn]=Залгагдсан DVD
+Comment[ms]=DVD Terlekap
+Comment[mt]=DVD immontat
+Comment[nb]=Montert DVD
+Comment[nds]=Inhangt DVD
+Comment[ne]=माउन्ट गरिएको डी भी डी
+Comment[nl]=Aangekoppelde dvd-romschijf
+Comment[nn]=Montert DVD
+Comment[pa]=ਮਾਊਟ ਕੀਤੀ DVD
+Comment[pl]=Zamontowany DVD
+Comment[pt]=DVD montado
+Comment[pt_BR]=DVD Montado
+Comment[ro]=DVD montat
+Comment[ru]=Смонтированный DVD
+Comment[rw]=DVD Yashyizwemo
+Comment[se]=Čatnon DVD
+Comment[sk]=Pripojené DVD
+Comment[sl]=Priklopljen DVD
+Comment[sr]=Монтиран DVD
+Comment[sr@Latn]=Montiran DVD
+Comment[sv]=Monterad dvd
+Comment[ta]=ஏற்றப்பட்ட சிடிராம்
+Comment[tg]=Монтажшудаи DVD
+Comment[th]=ดีวีดีที่เม้านท์แล้ว
+Comment[tr]=Bağlı DVD
+Comment[tt]=Totaşqan DVD
+Comment[uk]=Змонтований DVD
+Comment[uz]=Ulangan DVD
+Comment[uz@cyrillic]=Уланган DVD
+Comment[vi]=DVD đã kết nối
+Comment[wa]=Plake lazer DVD montêye
+Comment[zh_CN]=挂载的 DVD
+Comment[zh_TW]=已掛載的 DVD-ROM
+Patterns=
+
+X-KDE-AutoEmbed=true
+X-KDE-IsAlso=inode/directory
diff --git a/kioslave/media/mimetypes/dvd_unmounted.desktop b/kioslave/media/mimetypes/dvd_unmounted.desktop
new file mode 100644
index 000000000..918f7cd00
--- /dev/null
+++ b/kioslave/media/mimetypes/dvd_unmounted.desktop
@@ -0,0 +1,81 @@
+[Desktop Entry]
+Icon=dvd_unmount
+Type=MimeType
+MimeType=media/dvd_unmounted
+Comment=Unmounted DVD
+Comment[af]=Ontkoppelde DVD
+Comment[ar]=DVD غير محمّل
+Comment[az]=Ayrılmış DVD
+Comment[be]=Адмацаваны DVD
+Comment[bg]=Демонтиран DVD диск
+Comment[bn]=আনমাউন্ট করা ডিভিডি
+Comment[br]=DVD-ROM divountet
+Comment[bs]=Demontiran DVD
+Comment[ca]=DVD desmuntat
+Comment[cs]=Odpojené DVD
+Comment[csb]=Òdmòntowóny nëk DVD
+Comment[cy]=DVD wedi'i ddadosod
+Comment[da]=Afmonteret dvd
+Comment[de]=Nicht eingebundene DVD
+Comment[el]=Αποπροσαρτημένο DVD
+Comment[eo]=Demetita DVD
+Comment[es]=DVD desmontado
+Comment[et]=Lahutatud DVD
+Comment[eu]=DVD desmuntatua
+Comment[fa]=DVD پیاده‌شده
+Comment[fi]=Irrotettu DVD-levy
+Comment[fr]=DVD-ROM non monté(s)
+Comment[fy]=Ofkeppele Dûbelskiif
+Comment[ga]=DVD neamhfheistithe
+Comment[gl]=DVD non Montado
+Comment[he]=כונן DVD מנותק
+Comment[hi]=अनमाउन्टेड डीवीडी
+Comment[hr]=Nepristupljeni DVD
+Comment[hu]=Leválasztott DVD
+Comment[is]=Aftengt DVD
+Comment[it]=DVD smontato
+Comment[ja]=マウントされていない DVD
+Comment[ka]=დემონტირებული DVD
+Comment[kk]=Тіркеуден шығарған DVD
+Comment[km]=ឌីវីឌី​ដែល​មិន​បាន​រៀបចំ
+Comment[lo]=ຫັງກາລີ
+Comment[lt]=Išmontuotas DVD
+Comment[lv]=Nomontēts DVD
+Comment[mk]=Одмонтиран DVD
+Comment[mn]=Салгаатай DVD
+Comment[ms]=DVD Nyahlekap
+Comment[mt]=DVD mhux immontat
+Comment[nb]=Avmontert DVD
+Comment[nds]=Afhangt DVD
+Comment[ne]=अनमाउन्ट गरिएको डी भी डी
+Comment[nl]=Afgekoppelde dvd-romschijf
+Comment[nn]=Avmontert DVD
+Comment[pa]=ਅਨਮਾਊਟ ਕੀਤੀ DVD
+Comment[pl]=Odmontowany DVD
+Comment[pt]=DVD desmontado
+Comment[pt_BR]=DVD Desmontado
+Comment[ro]=DVD nemontat
+Comment[ru]=Отмонтированный DVD
+Comment[rw]=DVD Yakuwemo
+Comment[se]=Gálgajuvvon DVD
+Comment[sk]=Nepripojené DVD
+Comment[sl]=Odklopljen DVD
+Comment[sr]=Демонтиран DVD
+Comment[sr@Latn]=Demontiran DVD
+Comment[sv]=Avmonterad dvd
+Comment[ta]=இறக்கப்பட்ட சிடிராம்
+Comment[tg]=Ғайри монтажшудаи DVD
+Comment[th]=ดีวีดีที่ไม่ได้เม้านท์
+Comment[tr]=Ayrılmış DVD
+Comment[tt]=Totaşmağan DVD
+Comment[uk]=Демонтований DVD
+Comment[uz]=Ulanmagan DVD
+Comment[uz@cyrillic]=Уланмаган DVD
+Comment[vi]=DVD đã gỡ ra
+Comment[wa]=Plake lazer DVD dismontêye
+Comment[zh_CN]=未挂载的 DVD
+Comment[zh_TW]=未掛載的 DVD-ROM
+Patterns=
+
+X-KDE-AutoEmbed=true
+X-KDE-IsAlso=inode/directory
diff --git a/kioslave/media/mimetypes/dvdvideo.desktop b/kioslave/media/mimetypes/dvdvideo.desktop
new file mode 100644
index 000000000..756919293
--- /dev/null
+++ b/kioslave/media/mimetypes/dvdvideo.desktop
@@ -0,0 +1,73 @@
+[Desktop Entry]
+Type=MimeType
+MimeType=media/dvdvideo
+Comment=DVD Video Disk
+Comment[af]=DVD Video skyf
+Comment[ar]=قرص رقمي مرئي للمرئيات
+Comment[be]=Відэадыск DVD
+Comment[bg]=Видео DVD диск
+Comment[bn]=ডিভিডি ভিডিও ডিস্ক
+Comment[br]=Pladenn DVD Video
+Comment[bs]=DVD video disk
+Comment[ca]=Vídeo disc DVD
+Comment[cs]=DVD video
+Comment[csb]=Disk DVD Video
+Comment[da]=Dvd video-disk
+Comment[de]=DVD Video-Disk
+Comment[el]=Δίσκος DVD (βίντεο)
+Comment[eo]=DVDa videodisko
+Comment[es]=Disco de video DVD
+Comment[et]=DVD videoplaat
+Comment[eu]=DVD bideo diska
+Comment[fa]=دیسک ویدیویی DVD
+Comment[fi]=DVD-videolevy
+Comment[fr]=DVD vidéo
+Comment[fy]=Dûbelskiif Fideoskiif
+Comment[ga]=Físdiosca DVD
+Comment[gl]=DVD de vídeo
+Comment[he]=תקליטור וידאו של DVD
+Comment[hi]=डीवीडी वीडियो डिस्क
+Comment[hr]=DVD video disk
+Comment[hu]=DVD-videolemez
+Comment[is]=DVD vídeódiskur
+Comment[it]=Disco video DVD
+Comment[ja]=DVD ビデオディスク
+Comment[ka]=ვიდეო DVD დისკი
+Comment[kk]=DVD бейне дискі
+Comment[km]=ថាស​វីដេអូ ឌីវីឌី
+Comment[lt]=DVD video diskas
+Comment[lv]=DVD Video Disks
+Comment[mk]=DVD Видеодиск
+Comment[ms]=Cakera Video DVD
+Comment[nb]=DVD-videoplate
+Comment[nds]=DVD-Videodisk
+Comment[ne]=डी भी डी भिडियो डिस्क
+Comment[nl]=DVD Videodisk
+Comment[nn]=DVD-videoplate
+Comment[pa]=DVD ਵੀਡਿਓ ਡਿਸਕ
+Comment[pl]=Płyta DVD Video
+Comment[pt]=Disco DVD de Vídeo
+Comment[pt_BR]=DVD de vídeo
+Comment[ro]=Disc video DVD
+Comment[ru]=DVD с видео
+Comment[rw]=Disiki Videwo DVD
+Comment[se]=DVD-videoskearru
+Comment[sk]=DVD Video disk
+Comment[sl]=DVD Video disk
+Comment[sr]=DVD видео диск
+Comment[sr@Latn]=DVD video disk
+Comment[sv]=Dvd-videoskiva
+Comment[ta]=டிவிடி படக்காட்சி வட்டு
+Comment[te]=డివిడి విడియొ డిస్క్
+Comment[th]=แผ่นดีวีดีภาพยนตร์
+Comment[tr]=DVD Video
+Comment[uk]=Відео диск DVD
+Comment[uz]=DVD video-disk
+Comment[uz@cyrillic]=DVD видео-диск
+Comment[vi]=Đĩa Video DVD
+Comment[wa]=Plake videyo DVD
+Comment[zh_CN]=DVD 影碟
+Comment[zh_TW]=DVD 視訊光碟
+Icon=dvd_unmount
+
+X-KDE-IsAlso=inode/directory
diff --git a/kioslave/media/mimetypes/floppy5_mounted.desktop b/kioslave/media/mimetypes/floppy5_mounted.desktop
new file mode 100644
index 000000000..b0284cadb
--- /dev/null
+++ b/kioslave/media/mimetypes/floppy5_mounted.desktop
@@ -0,0 +1,85 @@
+[Desktop Entry]
+Icon=5floppy_mount
+Type=MimeType
+MimeType=media/floppy5_mounted
+Comment=Mounted 5¼" Floppy
+Comment[af]=Gekoppelde 5¼" Sagteskyf
+Comment[ar]=قرص مرن 5.25 محمّل
+Comment[az]=Bağlanmış 5¼" Floppi
+Comment[be]=Прымацаваная дыскета 5¼"
+Comment[bg]=Монтирано 5¼" флопи
+Comment[bn]=মাউন্ট করা 5¼" ফ্লপি
+Comment[br]=Pladennig 5¼" marc'het
+Comment[bs]=Montirana 5?" disketa
+Comment[ca]=Disquet 5¼" muntat
+Comment[cs]=Připojená disketa 5¼"
+Comment[csb]=Zamòntowónô disczétka 5¼"
+Comment[cy]=Disg meddal 5.25" wedi'i osod
+Comment[da]=Monteret 5¼"-floppy
+Comment[de]=Eingebundene 5¼"-Diskette
+Comment[el]=Προσαρτημένη δισκέτα 5¼"
+Comment[eo]=Surmetita 5¼"-Disketo
+Comment[es]=Disquete 5¼" montado
+Comment[et]=Ühendatud 5¼" flopi
+Comment[eu]=5¼"ko diskete muntatua
+Comment[fa]=فلاپی 5¼" سوارشده
+Comment[fi]=Liitetty 5¼"-levyke
+Comment[fr]=Disquette 5¼" montée
+Comment[fy]=Oankeppele 5¼" Skiif
+Comment[ga]=Diosca flapach 5¼" feistithe
+Comment[gl]=Disquete 5¼" Montado
+Comment[he]=תקליטון "¼5 מחובר
+Comment[hi]=माउन्टेड 5¼" फ़्लॉपी
+Comment[hr]=Pristupljena 5¼" disketa
+Comment[hu]=Csatlakoztatott 5¼"-es floppy
+Comment[is]=Tengdur 5¼" disklingur
+Comment[it]=Dischetto da 5¼" montato
+Comment[ja]=マウントされた 5 インチフロッピー
+Comment[ka]=მონტირებული დისკწამყვანი 5¼"
+Comment[kk]=Тіркеген 5¼" иілгіш диск
+Comment[km]=5¼" Floppy បាន​រៀបចំ
+Comment[lo]=ຟໍແມດຟອປີ້ - K
+Comment[lt]=Sumontuotas 5¼" lankstus diskelis
+Comment[lv]=Piemontēta 5¼" diskete
+Comment[mk]=Монтирана 5¼" дискета
+Comment[mn]=Залгагдсан 5¼"-Уян диск
+Comment[ms]=Liut 5¼" Terlekap
+Comment[mt]=Flopi 5¼" immontat
+Comment[nb]=Montert 5¼" diskett
+Comment[nds]=Inhangt 5¼"-Diskett
+Comment[ne]=माउन्ट गरिएको 5¼" फ्लपी
+Comment[nl]=Aangekoppelde 5¼" diskette
+Comment[nn]=Montert 5¼"-diskett
+Comment[nso]=Floppy yeo e Nameleditswego ya 5¼"
+Comment[pa]=ਮਾਊਟ 5¼" ਫਲਾਪੀ
+Comment[pl]=Zamontowana dyskietka 5¼"
+Comment[pt]=Disquete de 5¼" montada
+Comment[pt_BR]=Disquete 5¼" Montado
+Comment[ro]=Dischetă 5¼" montată
+Comment[ru]=Смонтированная дискета 5¼"
+Comment[rw]=Disikete 5¼" Yashyizwemo
+Comment[se]=Čatnon 5¼-dibmaskearru
+Comment[sk]=Pripojená disketa 5¼"
+Comment[sl]=Priklopljena disketna enota 5¼"
+Comment[sr]=Монтиран 5¼" флопи
+Comment[sr@Latn]=Montiran 5¼" flopi
+Comment[sv]=Monterad 5¼"-diskett
+Comment[ta]=ஏற்றப்பட்ட 5¼" நெகிழ்வட்டு
+Comment[tg]=Монтажшудаи 5¼" Флоппи
+Comment[th]=ฟล็อปปี 5" ที่เม้านท์แล้ว
+Comment[tr]=Bağlı 5¼" Disket
+Comment[tt]=Totaşqan 5¼" Floppy
+Comment[uk]=Змонтований флопі 5¼"
+Comment[uz]=Ulangan 5¼"disket
+Comment[uz@cyrillic]=Уланган 5¼"дискет
+Comment[ven]=5¼" Floppy yo gonyiswaho
+Comment[vi]=Đĩa mềm 5¼" đã kết nối
+Comment[wa]=Plakete 5" ¼ montêye
+Comment[xh]=Elayishiweyo 5¼" Floppy
+Comment[zh_CN]=挂载的 5.25 英寸软驱
+Comment[zh_TW]=已掛載的軟碟機
+Comment[zu]=I-5¼" Floppy eyenyusiwe
+Patterns=
+
+X-KDE-AutoEmbed=true
+X-KDE-IsAlso=inode/directory
diff --git a/kioslave/media/mimetypes/floppy5_unmounted.desktop b/kioslave/media/mimetypes/floppy5_unmounted.desktop
new file mode 100644
index 000000000..53e53b46f
--- /dev/null
+++ b/kioslave/media/mimetypes/floppy5_unmounted.desktop
@@ -0,0 +1,85 @@
+[Desktop Entry]
+Icon=5floppy_unmount
+Type=MimeType
+MimeType=media/floppy5_unmounted
+Comment=Unmounted 5¼" Floppy
+Comment[af]=Ontkoppelde 5¼" Sagteskyf
+Comment[ar]=قرص مرن 5.25 غير محمّل
+Comment[az]=Ayrılmış 5¼" Floppi
+Comment[be]=Адмацаваная дыскета 5¼"
+Comment[bg]=Демонтирано 5¼" флопи
+Comment[bn]=আনমাউন্ট করা 5¼" ফ্লপি
+Comment[br]=Pladennig 5¼" divountet
+Comment[bs]=Demontirana 5?" disketa
+Comment[ca]=Disquet 5¼" desmuntat
+Comment[cs]=Odpojená disketa 5¼"
+Comment[csb]=Òdmòntowónô disczétka 5¼"
+Comment[cy]=Disg meddal 5.25" wedi'i ddadosod
+Comment[da]=Afmonteret 5¼"-floppy
+Comment[de]=Nicht eingebundene 5¼"-Diskette
+Comment[el]=Αποπροσαρτημένη δισκέτα 5¼"
+Comment[eo]=Demetita 5¼"-Disketo
+Comment[es]=Disquete 5¼" desmontado
+Comment[et]=Lahutatud 5¼" flopi
+Comment[eu]=5¼"ko diskete desmuntatua
+Comment[fa]=فلاپی 5¼" پیاده‌شده
+Comment[fi]=Irrotettu 5¼"-levyke
+Comment[fr]=Disquette 5¼" non montée
+Comment[fy]=Ofkeppele 5¼" Skiif
+Comment[ga]=Diosca flapach 5¼" neamhfheistithe
+Comment[gl]=Disquete 5¼" Non Montado
+Comment[he]=תקליטון "¼5 מנותק
+Comment[hi]=अनमाउन्टेड 5¼" फ़्लॉपी
+Comment[hr]=Nepristupljena 5¼" disketa
+Comment[hu]=Leválasztott 5¼"-es floppy
+Comment[is]=Aftengdur 5¼" disklingur
+Comment[it]=Dischetto da 5¼" non montato
+Comment[ja]=マウントされていない 5 インチフロッピー
+Comment[ka]=დემონტირებული დისკწამყვანი 5¼"
+Comment[kk]=Тіркеуден шығарған 5¼" иілгіш дискі
+Comment[km]=5¼" Floppy មិន​បាន​រៀបចំ
+Comment[lo]=ຫັງກາລີ
+Comment[lt]=Išmontuotas 5¼" lankstus diskelis
+Comment[lv]=Nomontēta 5¼" diskete
+Comment[mk]=Одмонтирана 5¼" дискета
+Comment[mn]=Салгагдсан 5¼"-Уян диск
+Comment[ms]=Liut 5¼" Terlekap
+Comment[mt]=Flopi 5¼" mhux immontat
+Comment[nb]=Avmontert 5¼" diskett
+Comment[nds]=Afhangt 5¼"-Diskett
+Comment[ne]=अनमाउन्ट गरिएको 5¼" फ्लपी
+Comment[nl]=Afgekoppelde 5¼" diskette
+Comment[nn]=Avmontert 5¼"-diskett
+Comment[nso]=Floppy yeo e Theositswego ya 5¼"
+Comment[pa]=ਅਨਮਾਊਟ 5¼" ਫਲਾਪੀ
+Comment[pl]=Odmontowana dyskietka 5¼"
+Comment[pt]=Disquete de 5¼" desmontada
+Comment[pt_BR]=Disquete 5¼" Desmontado
+Comment[ro]=Dischetă 5¼" nemontată
+Comment[ru]=Отмонтированная дискета 5¼"
+Comment[rw]=Disikete 5¼" Yakuwemo
+Comment[se]=Gálgajuvvon 5¼-dibmaskearru
+Comment[sk]=Nepripojená disketa 5¼"
+Comment[sl]=Odklopljena disketna enota 5¼"
+Comment[sr]=Демонтиран 5¼" флопи
+Comment[sr@Latn]=Demontiran 5¼" flopi
+Comment[sv]=Avmonterad 5¼"-diskett
+Comment[ta]=வெளியேற்றிய 5¼" நெகிழ்வட்டு
+Comment[tg]=Ҷудо шудаи 5¼" Флоппи
+Comment[th]=ฟล็อปปี 5" ที่ไม่ได้เม้านท์
+Comment[tr]=Bağlı olmayan 5¼" Disket
+Comment[tt]=Totaşqan 5¼" Floppy
+Comment[uk]=Демонтований флопі 5¼"
+Comment[uz]=Ulanmagan 5¼"disket
+Comment[uz@cyrillic]=Уланмаган 5¼"дискет
+Comment[ven]=5¼" Floppy i songo gonyiswaho
+Comment[vi]=Đĩa mềm 5¼" đã gỡ ra
+Comment[wa]=Plakete 5" ¼ dismontêye
+Comment[xh]=Enganyuswanga 5¼" Floppy
+Comment[zh_CN]=未挂载的 5.25 英寸软驱
+Comment[zh_TW]=未掛載的軟碟機
+Comment[zu]=I-5¼" Floppy Yehlisiwe
+Patterns=
+
+X-KDE-AutoEmbed=true
+X-KDE-IsAlso=inode/directory
diff --git a/kioslave/media/mimetypes/floppy_mounted.desktop b/kioslave/media/mimetypes/floppy_mounted.desktop
new file mode 100644
index 000000000..0a51605fd
--- /dev/null
+++ b/kioslave/media/mimetypes/floppy_mounted.desktop
@@ -0,0 +1,85 @@
+[Desktop Entry]
+Icon=3floppy_mount
+Type=MimeType
+MimeType=media/floppy_mounted
+Comment=Mounted Floppy
+Comment[af]=Gekoppelde Sagteskyf
+Comment[ar]=قرص مرن محمّل
+Comment[az]=Bağlanmış Floppi
+Comment[be]=Прымацаваная дыскета
+Comment[bg]=Монтирано флопи
+Comment[bn]=মাউন্ট করা ফ্লপি
+Comment[br]=Pladennig marc'het
+Comment[bs]=Montirana disketa
+Comment[ca]=Disquet muntat
+Comment[cs]=Připojená disketa
+Comment[csb]=Zamòntowónô disczétka
+Comment[cy]=Disg meddal wedi'i osod
+Comment[da]=Monteret floppy
+Comment[de]=Eingebundene Diskette
+Comment[el]=Προσαρτημένη δισκέτα
+Comment[eo]=Surmetita Disketo
+Comment[es]=Disquete montado
+Comment[et]=Ühendatud flopi
+Comment[eu]=Diskete muntatua
+Comment[fa]=فلاپی سوارشده
+Comment[fi]=Liitetty levyke
+Comment[fr]=Disquette montée
+Comment[fy]=Oankeppele Skiif
+Comment[ga]=Diosca flapach feistithe
+Comment[gl]=Disquete Montado
+Comment[he]=תקליטון מחובר
+Comment[hi]=माउन्टेड फ़्लॉपी
+Comment[hr]=Pristupljena disketa
+Comment[hu]=Csatlakoztatott floppy
+Comment[is]=Tengdur disklingur
+Comment[it]=Dischetto montato
+Comment[ja]=マウントされたフロッピー
+Comment[ka]=მონტირებული დრეკადი დისკი
+Comment[kk]=Тііркеген иілгіш диск
+Comment[km]=Floppy បាន​រៀបចំ
+Comment[lo]=ຟໍແມດຟອບປິ້້ - K
+Comment[lt]=Sumontuotas lankstus diskelis
+Comment[lv]=Piemontēta diskete
+Comment[mk]=Монтирана дискета
+Comment[mn]=Залгаатай уян диск
+Comment[ms]=Liut Terlekap
+Comment[mt]=Flopi mmontat
+Comment[nb]=Montert diskett
+Comment[nds]=Inhangt Diskett
+Comment[ne]=माउन्ट गरिएको फ्लपी
+Comment[nl]=Aangekoppelde diskette
+Comment[nn]=Montert diskett
+Comment[nso]=Floppy yeo e Nameleditswego
+Comment[pa]=ਮਾਊਟ ਕੀਤੀ ਫਲਾਪੀ
+Comment[pl]=Zamontowana dyskietka
+Comment[pt]=Disquete montada
+Comment[pt_BR]=Disquete Montado
+Comment[ro]=Dischetă montată
+Comment[ru]=Смонтированная дискета
+Comment[rw]=Disikete Yashyizwemo
+Comment[se]=Čatnon dibmaskearru
+Comment[sk]=Pripojená disketa
+Comment[sl]=Priklopljena disketna enota
+Comment[sr]=Монтиран флопи
+Comment[sr@Latn]=Montiran flopi
+Comment[sv]=Monterad diskett
+Comment[ta]=இறக்கப்பட்ட நெகிழ்வட்டு
+Comment[tg]=Монтажшудаи Floppy
+Comment[th]=ฟล็อปปีที่เม้านท์แล้ว
+Comment[tr]=Bağlı Disket
+Comment[tt]=Totaşqan Floppy
+Comment[uk]=Змонтований флопі
+Comment[uz]=Ulangan disket
+Comment[uz@cyrillic]=Уланган дискет
+Comment[ven]=Floppy yo gonyiswaho
+Comment[vi]=Đĩa mềm đã kết nối
+Comment[wa]=Plakete montêye
+Comment[xh]=Floppy Enyusiweyo
+Comment[zh_CN]=挂载的软驱
+Comment[zh_TW]=已掛載的軟碟機
+Comment[zu]=I-Floppy eyenyusiwe
+Patterns=
+
+X-KDE-AutoEmbed=true
+X-KDE-IsAlso=inode/directory
diff --git a/kioslave/media/mimetypes/floppy_unmounted.desktop b/kioslave/media/mimetypes/floppy_unmounted.desktop
new file mode 100644
index 000000000..e17ab5557
--- /dev/null
+++ b/kioslave/media/mimetypes/floppy_unmounted.desktop
@@ -0,0 +1,85 @@
+[Desktop Entry]
+Icon=3floppy_unmount
+Type=MimeType
+MimeType=media/floppy_unmounted
+Comment=Unmounted Floppy
+Comment[af]=Ontkoppelde Sagteskyf
+Comment[ar]=قرص مرن غير محمّل
+Comment[az]=Ayrılmış FLoppi
+Comment[be]=Адмацаваная дыскета
+Comment[bg]=Демонтирано флопи
+Comment[bn]=আনমাউন্ট করা ফ্লপি
+Comment[br]=Pladennig divountet
+Comment[bs]=Demontirana disketa
+Comment[ca]=Disquet desmuntat
+Comment[cs]=Odpojená disketa
+Comment[csb]=Òdmòntowónô disczétka
+Comment[cy]=Disg meddal wedi'i ddadosod
+Comment[da]=Afmonteret floppy
+Comment[de]=Nicht eingebundene Diskette
+Comment[el]=Αποπροσαρτημένη δισκέτα
+Comment[eo]=Demetita Disketo
+Comment[es]=Disquete desmontado
+Comment[et]=Lahutatud flopi
+Comment[eu]=Diskete desmuntatua
+Comment[fa]=فلاپی پیاده‌شده
+Comment[fi]=Irrotettu levyke
+Comment[fr]=Disquette non montée
+Comment[fy]=Ofkeppele Skiif
+Comment[ga]=Diosca flapach neamhfheistithe
+Comment[gl]=Disquete non Montado
+Comment[he]=תקליטון מנותק
+Comment[hi]=अनमाउन्टेड फ़्लॉपी
+Comment[hr]=Nepristupljena disketa
+Comment[hu]=Leválasztott floppy
+Comment[is]=Aftengdur disklingur
+Comment[it]=Dischetto non montato
+Comment[ja]=マウントされていないフロッピー
+Comment[ka]=დემონტირებული დრეკადი დისკი
+Comment[kk]=Тіркеуден шығарған иілгіш диск
+Comment[km]=Floppy មិន​បាន​រៀបចំ
+Comment[lo]=ຫັງກາລີ
+Comment[lt]=Išmontuotas lankstus diskelis
+Comment[lv]=Nomontēta diskete
+Comment[mk]=Одмонтирана дискета
+Comment[mn]=Салгагдсан уян дискүүд
+Comment[ms]=Liut Nyahlekap
+Comment[mt]=Flopi mhux immontat
+Comment[nb]=Avmontert diskett
+Comment[nds]=Afhangt Diskett
+Comment[ne]=अनमाउन्ट गरिएको फ्लपी
+Comment[nl]=Afgekoppelde diskette
+Comment[nn]=Avmontert diskett
+Comment[nso]=Floppy yeo e Theositswego
+Comment[pa]=ਅਨਮਾਊਟ ਕੀਤੀ ਫਲਾਪੀ
+Comment[pl]=Odmontowana dyskietka
+Comment[pt]=Disquete desmontada
+Comment[pt_BR]=Disquete Desmontado
+Comment[ro]=Dischetă nemontată
+Comment[ru]=Отмонтированная дискета
+Comment[rw]=Disikete Yakuwemo
+Comment[se]=Gálgajuvvon dibmaskearru
+Comment[sk]=Nepripojená disketa
+Comment[sl]=Odklopljena disketna enota
+Comment[sr]=Демонтиран флопи
+Comment[sr@Latn]=Demontiran flopi
+Comment[sv]=Avmonterad diskett
+Comment[ta]=வெளியேற்றிய நெகிழ்வட்டு
+Comment[tg]=Ҷудо шудаи Floppy
+Comment[th]=ฟล็อปปีที่ไม่ถูกเม้านท์
+Comment[tr]=Bağlanmamış Disket
+Comment[tt]=Totaşmağan Floppy
+Comment[uk]=Демонтований флопі
+Comment[uz]=Ulanmagan disket
+Comment[uz@cyrillic]=Уланмаган дискет
+Comment[ven]=Floppy i songo gonyiswaho
+Comment[vi]=Đĩa mềm đã gỡ ra
+Comment[wa]=Plakete dismontêye
+Comment[xh]=Floppy Enganyuswanga
+Comment[zh_CN]=未挂载的软驱
+Comment[zh_TW]=未掛載的軟碟機
+Comment[zu]=I-Floppy eyehlisiwe
+Patterns=
+
+X-KDE-AutoEmbed=true
+X-KDE-IsAlso=inode/directory
diff --git a/kioslave/media/mimetypes/gphoto2camera.desktop b/kioslave/media/mimetypes/gphoto2camera.desktop
new file mode 100644
index 000000000..613d69767
--- /dev/null
+++ b/kioslave/media/mimetypes/gphoto2camera.desktop
@@ -0,0 +1,76 @@
+[Desktop Entry]
+Type=MimeType
+MimeType=media/gphoto2camera
+Comment=Camera
+Comment[af]=Kamera
+Comment[ar]=كاميرا
+Comment[az]=Kamera
+Comment[be]=Камера
+Comment[bg]=Фотоапарат
+Comment[bn]=ক্যামেরা
+Comment[br]=Kamera
+Comment[bs]=Kamera
+Comment[ca]=Càmera
+Comment[cs]=Kamera
+Comment[csb]=Òdjimkòwô kamera
+Comment[da]=Kamera
+Comment[de]=Kamera
+Comment[el]=Κάμερα
+Comment[eo]=Kamero
+Comment[es]=Cámara
+Comment[et]=Kaamera
+Comment[eu]=Kamara
+Comment[fa]=دوربین
+Comment[fi]=Kamera
+Comment[fr]=Nouvel appareil photo
+Comment[fy]=Kamera
+Comment[ga]=Ceamara
+Comment[gl]=Cámara
+Comment[he]=מצלמה
+Comment[hi]=कैमरा
+Comment[hr]=Kamera
+Comment[hu]=Fényképezőgép
+Comment[is]=Myndavél
+Comment[it]=Macchina fotografica
+Comment[ja]=カメラ
+Comment[ka]=კამერა
+Comment[kk]=Фотокамера
+Comment[km]=ម៉ាស៊ីន​ថត
+Comment[lt]=Fotoaparatas
+Comment[lv]=Kamera
+Comment[mk]=Камера
+Comment[ms]=Kamera
+Comment[nb]=Kamera
+Comment[nds]=Kamera
+Comment[ne]=क्यामेरा
+Comment[nn]=Kamera
+Comment[pa]=ਕੈਮਰਾ
+Comment[pl]=Aparat fotograficzny
+Comment[pt]=Máquina fotográfica
+Comment[pt_BR]=Câmera
+Comment[ro]=Aparat foto
+Comment[ru]=Камера
+Comment[rw]=Kamera
+Comment[se]=Govvanaperáhtta
+Comment[sk]=Digitálny fotoaparát
+Comment[sl]=Fotoaparat
+Comment[sr]=Камера
+Comment[sr@Latn]=Kamera
+Comment[sv]=Kamera
+Comment[ta]=புகைப்பட கருவி
+Comment[te]=కెమెరా
+Comment[tg]=Камера
+Comment[th]=กล้องดิจิตอล
+Comment[tr]=Kamera
+Comment[tt]=Kamera
+Comment[uk]=Камера
+Comment[uz]=Fotoaparat
+Comment[uz@cyrillic]=Фотоапарат
+Comment[vi]=Máy chụp ảnh số
+Comment[zh_CN]=相机
+Comment[zh_TW]=相機
+Icon=camera_unmount
+
+X-KDE-AutoEmbed=true
+X-KDE-IsAlso=inode/directory
+
diff --git a/kioslave/media/mimetypes/hdd_mounted.desktop b/kioslave/media/mimetypes/hdd_mounted.desktop
new file mode 100644
index 000000000..2ebb0b1cc
--- /dev/null
+++ b/kioslave/media/mimetypes/hdd_mounted.desktop
@@ -0,0 +1,77 @@
+[Desktop Entry]
+Icon=hdd_mount
+Type=MimeType
+MimeType=media/hdd_mounted
+Comment=Mounted Hard Disk Volume
+Comment[af]=Gekoppelde Hard Skyf Partisie
+Comment[ar]=تجزئة قرص صلب محمّلة
+Comment[az]=Bağlanmış Sabit Disk Bölməsi
+Comment[be]=Прымацаваны раздзел жорсткага дыска
+Comment[bg]=Монтиран дял на твърд диск
+Comment[bn]=মাউন্ট করা হার্ড ডিস্ক ভলিউম
+Comment[br]=Pladenn marc'het
+Comment[bs]=Montirana hard disk particija
+Comment[ca]=Disc dur muntat
+Comment[cs]=Připojený oddíl pevného disku
+Comment[csb]=Zamòntowónô particëjô cwiardi platë
+Comment[da]=Monteret harddisk-volumen
+Comment[de]=Eingebundene Festplattenpartition
+Comment[el]=Προσαρτημένη κατάτμηση σκληρού δίσκου
+Comment[eo]=Surmetita subdisko
+Comment[es]=Volumen de disco duro montado
+Comment[et]=Ühendatud kõvaketta partitsioon
+Comment[eu]=Diska gogorraren zatiketa muntatua
+Comment[fa]=حجم دیسک سخت سوارشده
+Comment[fi]=Liitetty kiintoleyosio
+Comment[fr]=Partition de disque dur montée
+Comment[fy]=Oankeppele Fêsteskiif folume
+Comment[ga]=Imleabhar Feistithe Diosca Crua
+Comment[gl]=Partición do Disco Duro Montada
+Comment[he]=מחיצת כונן קשיח מחוברת
+Comment[hi]=माउन्टेड हार्ड डिस्क वॉल्यूम
+Comment[hr]=Pristupljeni volumen tvrdog diska
+Comment[hu]=Csatlakoztatott merevlemezes partíció
+Comment[is]=Tengd disksneið
+Comment[it]=Volume disco rigido montato
+Comment[ja]=マウントされたハードディスクボリューム
+Comment[ka]=მონტირებული ხისტი დისკის ტომი
+Comment[kk]=Тіркеген қатқыл диск томы
+Comment[km]=ទំហំ​ថាស​រឹង​ដែល​បាន​រៀបចំ
+Comment[lt]=Sumontuotas kieto disko skirsnis
+Comment[lv]=Piemontēts cietais disks
+Comment[mk]=Монтирана партиција на тврд диск
+Comment[ms]=Volum Cakera Keras Terlekap
+Comment[mt]=Partizzjoni ta' ħard-disk immuntata
+Comment[nb]=Montert harddiskpartisjon
+Comment[nds]=Inhangt Fastplaat-Partitschoon
+Comment[ne]=माउन्ट गरिएको हार्ड डिस्क भोल्युम
+Comment[nl]=Aangekoppelde hardeschijfpartitie
+Comment[nn]=Montert harddiskvolum
+Comment[pa]=ਮਾਊਟ ਕੀਤਾ ਹਾਰਡ ਡਿਸਕ ਭਾਗ
+Comment[pl]=Zamontowana partycja dysku twardego
+Comment[pt]=Volume de disco rígido montado
+Comment[pt_BR]=Volume do HD Montado
+Comment[ro]=Volum de hard disc montat
+Comment[ru]=Смонтированный раздел жёсткого диска
+Comment[rw]=Ububiko Disiki Bwashyizwemo
+Comment[se]=Čatnon garraskearrooassi
+Comment[sk]=Pripojený oddiel pevného disku
+Comment[sl]=Priklopljen pogon trdega diska
+Comment[sr]=Монтирана партиција хард диска
+Comment[sr@Latn]=Montirana particija hard diska
+Comment[sv]=Monterad hårdiskpartition
+Comment[ta]=ஏற்றப்பட்ட வன்தகடு வட்டு பிரிவு
+Comment[th]=ฮาร์ดดิสก์ที่เม้านท์แล้ว
+Comment[tr]=Bağlanmış Sabit Disk Bölümü
+Comment[tt]=Totaşqan Qatı Disk Töpläme
+Comment[uk]=Змонтований розділ жорсткого диску
+Comment[uz]=Qattiq diskning ulangan qismi
+Comment[uz@cyrillic]=Қаттиқ дискнинг уланган қисми
+Comment[vi]=Các Phân vùng Ổ cứng đã kết nối
+Comment[wa]=Volume del deure plake monté
+Comment[zh_CN]=挂载的硬盘卷
+Comment[zh_TW]=已掛載的硬碟分割區
+Patterns=
+
+X-KDE-AutoEmbed=true
+X-KDE-IsAlso=inode/directory
diff --git a/kioslave/media/mimetypes/hdd_unmounted.desktop b/kioslave/media/mimetypes/hdd_unmounted.desktop
new file mode 100644
index 000000000..fe9fc4f88
--- /dev/null
+++ b/kioslave/media/mimetypes/hdd_unmounted.desktop
@@ -0,0 +1,77 @@
+[Desktop Entry]
+Icon=hdd_unmount
+Type=MimeType
+MimeType=media/hdd_unmounted
+Comment=Unmounted Hard Disk Volume
+Comment[af]=Ontkoppelde Hard Skyf Partisie
+Comment[ar]=تجزئة قرص صلب غير محمّلة
+Comment[az]=Ayrılmış Sabit Disk Bölməsi
+Comment[be]=Адмацаваны раздзел жорсткага дыска
+Comment[bg]=Демонтиран дял на твърд диск
+Comment[bn]=আনমাউন্ট করা হার্ড ডিস্ক ভলিউম
+Comment[br]=Pladenn divarc'het
+Comment[bs]=Demontirana hard disk particija
+Comment[ca]=Disc dur desmuntat
+Comment[cs]=Odpojený oddíl pevného disku
+Comment[csb]=Òdmòntowónô particëjô cwiardi platë
+Comment[da]=Afmonteret harddisk-volumen
+Comment[de]=Nicht eingebundene Festplattenpartition
+Comment[el]=Αποπροσαρτημένη κατάτμηση σκληρού δίσκου
+Comment[eo]=Demetita subdisko
+Comment[es]=Volumen de disco duro desmontado
+Comment[et]=Lahutatud kõvaketta partitsioon
+Comment[eu]=Diska gogorraren zatiketa desmuntatua
+Comment[fa]=حجم دیسک سخت پیاده‌شده
+Comment[fi]=Irrotettu kiintolevyosio
+Comment[fr]=Partition de disque dur non montée
+Comment[fy]=Ofkeppele Fêsteskiif folume
+Comment[ga]=Imleabhar Diosca Crua Gan Fheistiú
+Comment[gl]=Partición do Disco Duro Non Montada
+Comment[he]=מחיצת כונן קשיח מנותקת
+Comment[hi]=अनमाउन्टेड हार्ड डिस्क वॉल्यूम
+Comment[hr]=Nepristupljeni volumen tvrdog diska
+Comment[hu]=Leválasztott merevlemezes partíció
+Comment[is]=Aftengd disksneið
+Comment[it]=Volume disco rigido non montato
+Comment[ja]=マウントされていないハードディスクボリューム
+Comment[ka]=დემონტირებული ხისტი დისკის ტომი
+Comment[kk]=Тіркеуден шығарған қатқыл диск томы
+Comment[km]=ទំហំ​ថាស​រឹង​ដែល​មិន​បាន​រៀបចំ
+Comment[lt]=Išmontuotas kieto disko skirsnis
+Comment[lv]=Nomontēts cietais disks
+Comment[mk]=Одмонтирана партиција на тврд диск
+Comment[ms]=Volum Cakera Keras Nyahlekap
+Comment[mt]=Partizzjoni ta' ħard-disk mhux immuntata
+Comment[nb]=Avmontert harddiskpartisjon
+Comment[nds]=Afhangt Fastplaat-Partitschoon
+Comment[ne]=अनमाउन्ट गरिएको हार्ड डिस्क भोल्युम
+Comment[nl]=Afgekoppelde hardeschijfpartitie
+Comment[nn]=Umontert harddiskvolum
+Comment[pa]=ਅਨਮਾਊਟ ਕੀਤੀ ਹਾਰਡ ਡਿਸਕ ਭਾਗ
+Comment[pl]=Odmontowana partycja dysku twardego
+Comment[pt]=Volume de disco rígido desmontado
+Comment[pt_BR]=Volume do HD Desmontado
+Comment[ro]=Volum de hard disc nemontat
+Comment[ru]=Отмонтированный раздел жёсткого диска
+Comment[rw]=Ububiko Disiki Bwakuwemo
+Comment[se]=Gálgajuvvon garraskearrooassi
+Comment[sk]=Odpojený oddiel pevného disku
+Comment[sl]=Odklopljen pogon trdega diska
+Comment[sr]=Демонтирана партиција хард диска
+Comment[sr@Latn]=Demontirana particija hard diska
+Comment[sv]=Avmonterad hårdiskpartition
+Comment[ta]=வெளியேற்றப்பட்ட வன்வட்டு பகுதி
+Comment[th]=ฮาร์ดดิสก์ที่ไม่ได้เม้านท์
+Comment[tr]=Ayrılmış Sabit Disk Bölümü
+Comment[tt]=Totaşmağan Qatı Disk Töpläme
+Comment[uk]=Демонтований розділ жорсткого диску
+Comment[uz]=Qattiq diskning ulanmagan qismi
+Comment[uz@cyrillic]=Қаттиқ дискнинг уланмаган қисми
+Comment[vi]=Các Phân vùng Ổ cứng đã gỡ ra
+Comment[wa]=Volume del deure plake dismonté
+Comment[zh_CN]=未挂载的硬盘卷
+Comment[zh_TW]=未掛載的硬碟分割區
+Patterns=
+
+X-KDE-AutoEmbed=true
+X-KDE-IsAlso=inode/directory
diff --git a/kioslave/media/mimetypes/nfs_mounted.desktop b/kioslave/media/mimetypes/nfs_mounted.desktop
new file mode 100644
index 000000000..ea64bdca6
--- /dev/null
+++ b/kioslave/media/mimetypes/nfs_mounted.desktop
@@ -0,0 +1,77 @@
+[Desktop Entry]
+Icon=nfs_mount
+Type=MimeType
+MimeType=media/nfs_mounted
+Comment=Mounted NFS Share
+Comment[af]=Gekoppelde NFS Hulpbron
+Comment[ar]=مشاركة NFS مركبة
+Comment[az]=Bağlanmış NFS Sahəsi
+Comment[be]=Прымацаваная агульная тэчка NFS
+Comment[bg]=Монтиран NFS ресурс
+Comment[bn]=মাউন্ট করা এন-এফ-এস শেয়ার
+Comment[br]=Rennad NFS marc'het
+Comment[bs]=Montiran NFS resurs
+Comment[ca]=Recurs NFS muntat
+Comment[cs]=Připojený zdroj NFS
+Comment[csb]=Zamòntowónô systema lopków NFS
+Comment[da]=Monteret NFS-share
+Comment[de]=Eingebundene NFS-Freigabe
+Comment[el]=Προσαρτημένος πόρος NFS
+Comment[eo]=Surmetita NFS-opuzaĵo
+Comment[es]=Recurso NFS montado
+Comment[et]=Ühendatud NFS ressurss
+Comment[eu]=NFS baliabide muntatua
+Comment[fa]=مشترک NFS سوارشده
+Comment[fi]=Liitetty NFS-jako
+Comment[fr]=Ressource NFS montée
+Comment[fy]=Oankeppele NFS-boarne
+Comment[ga]=Comhroinn Fheistithe NFS
+Comment[gl]=Compartición NFS Montada
+Comment[he]=משאב NFS מחובר
+Comment[hi]=माउन्टेड एनएफ़एस साझा
+Comment[hr]=Pristupljeno NFS dijeljenje
+Comment[hu]=Csatlakoztatott NFS-megosztás
+Comment[is]=Tengd NFS auðlind
+Comment[it]=Risorsa NFS montata
+Comment[ja]=マウントされた NFS 共有
+Comment[ka]=მონტირებული NFS რესურსი
+Comment[kk]=Тіркеген NFS ресурсы
+Comment[km]=NFS Share បាន​រៀបចំ
+Comment[lt]=Sumontuotas NFS bendro naudojimo resursas
+Comment[lv]=Piemontēta NFS šāre
+Comment[mk]=Монтиран NFS-ресурс
+Comment[ms]=Perkongsian NFS Terlekap
+Comment[mt]=Riżors NFS immuntat
+Comment[nb]=Montert NFS-ressurs
+Comment[nds]=Inhangt NFS-Freegaav
+Comment[ne]=माउन्ट गरिएको NFS साझेदारी
+Comment[nl]=Aangekoppelde NFS-gegevensbron
+Comment[nn]=Montert delt NFS-ressurs
+Comment[pa]=ਮਾਊਟ ਕੀਤੀ NFS ਸਾਂਝ
+Comment[pl]=Zamontowany system plików NFS
+Comment[pt]=Partilha de NFS montada
+Comment[pt_BR]=Volume NFS Montado
+Comment[ro]=Partajare NFS montată
+Comment[ru]=Смонтированный ресурс NFS
+Comment[rw]=Umugabane NFS Washyizwemo
+Comment[se]=Čatnon NFS-resursa
+Comment[sk]=Pripojený zdroj NFS
+Comment[sl]=Priklopljen vir NFS
+Comment[sr]=Монтирано NFS дељење
+Comment[sr@Latn]=Montirano NFS deljenje
+Comment[sv]=Monterad NFS-resurs
+Comment[ta]=ஏற்றப்பட்ட NFS பங்கு
+Comment[th]=ทรัพยากร NFS ที่ถูกเม้านท์
+Comment[tr]=Bağlı NFS Paylaşımı
+Comment[tt]=Totaşqan NFS Urtağı
+Comment[uk]=Змонтований ресурс NFS
+Comment[uz]=Ulangan NFS manba
+Comment[uz@cyrillic]=Уланган NFS манба
+Comment[vi]=Chia sẻ NFS đã kết nối
+Comment[wa]=Pårtaedje NFS monté
+Comment[zh_CN]=挂载的 NFS 共享
+Comment[zh_TW]=已掛載的 NFS 資源
+Patterns=
+
+X-KDE-AutoEmbed=true
+X-KDE-IsAlso=inode/directory
diff --git a/kioslave/media/mimetypes/nfs_unmounted.desktop b/kioslave/media/mimetypes/nfs_unmounted.desktop
new file mode 100644
index 000000000..d6ca31a68
--- /dev/null
+++ b/kioslave/media/mimetypes/nfs_unmounted.desktop
@@ -0,0 +1,77 @@
+[Desktop Entry]
+Icon=nfs_unmount
+Type=MimeType
+MimeType=media/nfs_unmounted
+Comment=Unmounted NFS Share
+Comment[af]=Ontkoppelde NFS Hulpbron
+Comment[ar]=مشاركة NFS غير مركبة
+Comment[az]=Ayrılmış NFS Sahəsi
+Comment[be]=Адмацаваная агульная тэчка NFS
+Comment[bg]=Демонтиран NFS ресурс
+Comment[bn]=আনমাউন্ট করা এন-এফ-এস শেয়ার
+Comment[br]=Rennad NFS divarc'het
+Comment[bs]=Demontiran NFS resurs
+Comment[ca]=Recurs NFS desmuntat
+Comment[cs]=Odpojený zdroj NFS
+Comment[csb]=Òdmòntowónô systema lopków NFS
+Comment[da]=Afmonteret NFS-share
+Comment[de]=Nicht eingebundene NFS-Freigabe
+Comment[el]=Αποπροσαρτημένος πόρος NFS
+Comment[eo]=Demetita NFS-opuzaĵo
+Comment[es]=Recurso NFS desmontado
+Comment[et]=Lahutatud NFS ressurss
+Comment[eu]=NFS baliabide desmuntatua
+Comment[fa]=مشترک NFS پیاده‌شده
+Comment[fi]=Irrotettu NFS-jako
+Comment[fr]=Ressource NFS non montée
+Comment[fy]=Oankeppele NFS-boarne
+Comment[ga]=Comhroinn NFS Gan Fheistiú
+Comment[gl]=Compartición NFS non Montada
+Comment[he]=משאב NFS מנותק
+Comment[hi]=अनमाउन्टेड एनएफ़एस साझा
+Comment[hr]=Nepristupljeno NFS dijeljenje
+Comment[hu]=Leválasztott NFS-megosztás
+Comment[is]=Aftengd NFS auðlind
+Comment[it]=Risorsa NFS non montata
+Comment[ja]=マウントされていない NFS 共有
+Comment[ka]=დემონტირებული NFS რესურსი
+Comment[kk]=Тіркеуден шығарған NFS ресурсы
+Comment[km]=NFS Share មិន​បាន​រៀបចំ
+Comment[lt]=Išmontuotas NFS bendro naudojimo resursas
+Comment[lv]=Nomontēta NFS šāre
+Comment[mk]=Одмонтиран NFS-ресурс
+Comment[ms]=Perkongsian NFS Nyahlekap
+Comment[mt]=Riżors NFS mhux immuntat
+Comment[nb]=Avmontert NFS-ressurs
+Comment[nds]=Afhangt NFS-Freegaav
+Comment[ne]=अनमाउन्ट गरिएको NFS साझेदारी
+Comment[nl]=Afgekoppelde NFS-gegevensbron
+Comment[nn]=Umontert delt NFS-ressurs
+Comment[pa]=ਅਨਮਾਊਟ ਕੀਤੀ NFS ਸਾਂਝ
+Comment[pl]=Odmontowany system plików NFS
+Comment[pt]=Partilha de NFS desmontada
+Comment[pt_BR]=Volume NFS Desmontado
+Comment[ro]=Partajare NFS nemontată
+Comment[ru]=Отмонтированный ресурс NFS
+Comment[rw]=Umugabane NFS Wakuwemo
+Comment[se]=Gálgajuvvon NFS-resursa
+Comment[sk]=Odpojený zdroj NFS
+Comment[sl]=Odklopljen vir NFS
+Comment[sr]=Демонтирано NFS дељење
+Comment[sr@Latn]=Demontirano NFS deljenje
+Comment[sv]=Avmonterad NFS-resurs
+Comment[ta]=இறக்கப்பட்ட NFS பங்கு
+Comment[th]=ทรัพยากร NFS ที่ไม่ถูกเม้านท์
+Comment[tr]=Bağlanmamış NFS Paylaşımı
+Comment[tt]=Totaşmağan NFS Urtağı
+Comment[uk]=Демонтований ресурс NFS
+Comment[uz]=Ulanmagan NFS manba
+Comment[uz@cyrillic]=Уланмаган NFS манба
+Comment[vi]=Chia sẻ NFS đã gỡ ra
+Comment[wa]=Pårtaedje NFS dismonté
+Comment[zh_CN]=未挂载的 NFS 共享
+Comment[zh_TW]=未掛載的 NFS 資源
+Patterns=
+
+X-KDE-AutoEmbed=true
+X-KDE-IsAlso=inode/directory
diff --git a/kioslave/media/mimetypes/removable_mounted.desktop b/kioslave/media/mimetypes/removable_mounted.desktop
new file mode 100644
index 000000000..83fc34e41
--- /dev/null
+++ b/kioslave/media/mimetypes/removable_mounted.desktop
@@ -0,0 +1,77 @@
+[Desktop Entry]
+Icon=usbpendrive_mount
+Type=MimeType
+MimeType=media/removable_mounted
+Comment=Mounted Removable Medium
+Comment[af]=Gekoppelde Verwyderbare Medium
+Comment[ar]=وسيط قابل للإزالة مركب
+Comment[az]=Bağlanmış Çıxarıla Bilən Mediyum
+Comment[be]=Прымацаваны зменны носьбіт
+Comment[bg]=Монтиран преносим носител
+Comment[bn]=মাউন্ট করা অপসারণযোগ্য মিডিয়াম
+Comment[br]=Medium lem-laka marc'het
+Comment[bs]=Montiran izmjenjivi uređaj
+Comment[ca]=Suport extraïble muntat
+Comment[cs]=Připojené výměnné médium
+Comment[csb]=Zamòntowóné òdłączalné medium
+Comment[da]=Monteret medie der kan fjernes
+Comment[de]=Eingebundenes Wechsellaufwerk
+Comment[el]=Προσαρτημένος αφαιρούμενο μέσο
+Comment[eo]=Surmetita forigebla datumportilo
+Comment[es]=Recurso extraíble montado
+Comment[et]=Ühendatud eemaldatav andmekandja
+Comment[eu]=Euskarri aldagarria muntatua
+Comment[fa]=رسانۀ برداشتنی سوارشده
+Comment[fi]=Liitetty irrotettava resurssi
+Comment[fr]=Média amovible monté
+Comment[fy]=Oankeppele ferwiderber medium
+Comment[ga]=Meán Feistithe Inbhainte
+Comment[gl]=Dispositivo Extraíbel Montado
+Comment[he]=מדיה חיצונית מחוברת
+Comment[hi]=माउन्टेड रीमूवेबल माध्यम
+Comment[hr]=Pristupljen izmjenjiv medij
+Comment[hu]=Csatlakoztatott adathordozó
+Comment[is]=Tengdur útskiptanlegur miðill
+Comment[it]=Supporto rimovibile montato
+Comment[ja]=マウントされたリムーバブルメディア
+Comment[ka]=მონტირებული პორტატიული მოწყობილობა
+Comment[kk]=Тіркеген ауыстырмалы тасушы
+Comment[km]=ឧបករណ៍​ចល័ត​ដែល​បាន​រៀបចំ
+Comment[lt]=Sumontuotas pašalinamas diskas
+Comment[lv]=Piemontēts noņemamais datu nesējs
+Comment[mk]=Монтиран отстранлив носач
+Comment[ms]=Medium Boleh Buang Terlekap
+Comment[mt]=Riżors NFS immuntat
+Comment[nb]=Montert flyttbart medium
+Comment[nds]=Inhangt tuuschbor Loopwark
+Comment[ne]=माउन्ट गरिएको हटाउन सकिने मेडिअम
+Comment[nl]=Aangekoppeld verwijderbaar medium
+Comment[nn]=Montert flyttbart medium
+Comment[pa]=ਮਾਊਟ ਕੀਤੇ ਹਟਾਉਣਯੋਗ ਮਾਧਿਅਮ
+Comment[pl]=Zamontowany nośnik wymienny
+Comment[pt]=Dispositivo amovível montado
+Comment[pt_BR]=Mídia Removível Montada
+Comment[ro]=Mediu amovibil montat
+Comment[ru]=Смонтированный внешний диск
+Comment[rw]=Igitangazamakuru Kivanwamo Cyashyizwemo
+Comment[se]=Čátnon sirdehahtti medium
+Comment[sk]=Pripojené vyberateľné médium
+Comment[sl]=Priklopljen odstranljiv medij
+Comment[sr]=Монтиран уклоњиви медијум
+Comment[sr@Latn]=Montiran uklonjivi medijum
+Comment[sv]=Monterad flyttbar enhet
+Comment[ta]=ஏற்றப்பட்ட நீக்கக்கூடிய மீடியம்
+Comment[th]=สื่อบันทึกแบบถอดออกได้ถูกเม้านท์
+Comment[tr]=Bağlı Ayrılabilir Ortam
+Comment[tt]=Totaşqan Çığarulı Media
+Comment[uk]=Змонтований переносний носій
+Comment[uz]=Ulangan saqlash uskunasi
+Comment[uz@cyrillic]=Уланган сақлаш ускунаси
+Comment[vi]=Ổ lưu trữ Di động đã kết nối
+Comment[wa]=Oiståve mediom monté
+Comment[zh_CN]=挂载的可移动介质
+Comment[zh_TW]=已掛載的可攜式媒體
+Patterns=
+
+X-KDE-AutoEmbed=true
+X-KDE-IsAlso=inode/directory
diff --git a/kioslave/media/mimetypes/removable_unmounted.desktop b/kioslave/media/mimetypes/removable_unmounted.desktop
new file mode 100644
index 000000000..6a8e3fada
--- /dev/null
+++ b/kioslave/media/mimetypes/removable_unmounted.desktop
@@ -0,0 +1,77 @@
+[Desktop Entry]
+Icon=usbpendrive_unmount
+Type=MimeType
+MimeType=media/removable_unmounted
+Comment=Unmounted Removable Medium
+Comment[af]=Ontkoppel Verwyderbare Medium
+Comment[ar]=وسيط قابل للإزالة غير مركب
+Comment[az]=Ayrılmış Çıxarıla Bilən Mediyum
+Comment[be]=Адмацаваны зменны носьбіт
+Comment[bg]=Демонтиран преносим носител
+Comment[bn]=আনমাউন্ট করা অপসারণযোগ্য মিডিয়াম
+Comment[br]=Medium ar skoroù lem/laka divarc'het
+Comment[bs]=Demontiran izmjenjivi uređaj
+Comment[ca]=Suport extraïble desmuntat
+Comment[cs]=Odpojené výměnné médium
+Comment[csb]=Òdmòntowóné òdłączalné medium
+Comment[da]=Afmonteret medie der kan fjernes
+Comment[de]=Nicht eingebundenes Wechsellaufwerk
+Comment[el]=Αποπροσαρτημένο αφαιρούμενο μέσο
+Comment[eo]=Demetita forigebla datumportilo
+Comment[es]=Recurso extraíble desmontado
+Comment[et]=Lahutatud eemaldatav andmekandja
+Comment[eu]=Euskarri aldagarria desmuntatua
+Comment[fa]=رسانۀ برداشتنی پیاده‌شده
+Comment[fi]=Irrotettu irrotettava resurssi
+Comment[fr]=Média amovible non monté
+Comment[fy]=Ofkeppele ferwiderber medium
+Comment[ga]=Meán Inbhainte Gan Fheistiú
+Comment[gl]=Dispositivo Extraíbel Non Montado
+Comment[he]=מדייה חיצונית מנותקת
+Comment[hi]=अनमाउन्टेड रीमूवेबल माध्यम
+Comment[hr]=Nepristupljen izmjenjiv medij
+Comment[hu]=Leválasztott adathordozó
+Comment[is]=Aftengdur útskiptanlegur miðill
+Comment[it]=Supporto rimovibile non montato
+Comment[ja]=マウントされていないリムーバブルメディア
+Comment[ka]=დემონტირებული პორტატიული მოწყობილობა
+Comment[kk]=Тіркеуден шығарған ауыстырмалы тасушы
+Comment[km]=ឧបករណ៍​ចល័ត​ដែល​មិន​បាន​រៀបចំ
+Comment[lt]=Išmontuotas pašalinamas diskas
+Comment[lv]=Nomontēts noņemamais datu nesējs
+Comment[mk]=Одмонтиран отстранлив носач
+Comment[ms]=Medium Boleh Buang Nyahlekap
+Comment[mt]=Riżors għall-ħażna tad-data mhux immuntat
+Comment[nb]=Avmontert flyttbart medium
+Comment[nds]=Afhangt tuuschbor Loopwark
+Comment[ne]=अनमाउन्ट गरिएको हटाउन सकिने मेडिअम
+Comment[nl]=Afgekoppeld verwijderbaar medium
+Comment[nn]=Umontert flyttbart medium
+Comment[pa]=ਅਨਮਾਊਟ ਕੀਤੀ ਹਟਾਉਣਯੋਗ ਮਾਧਿਅਮ
+Comment[pl]=Odmontowany nośnik wymienny
+Comment[pt]=Dispositivo amovível desmontado
+Comment[pt_BR]=Mídia Removível Desmontada
+Comment[ro]=Mediu amovibil nemontat
+Comment[ru]=Отмонтированный внешний диск
+Comment[rw]=Igitangazamakuru Kivanwamo Cyavanwemo
+Comment[se]=Gálgaduvvon sirdehahtti medium
+Comment[sk]=Odpojené vyberateľné médium
+Comment[sl]=Odklopljen odstranljiv medij
+Comment[sr]=Демонтиран уклоњиви медијум
+Comment[sr@Latn]=Demontiran uklonjivi medijum
+Comment[sv]=Avmonterad flyttbar enhet
+Comment[ta]=ஏற்றாத நீக்கக்கூடிய சாதனம்
+Comment[th]=สื่อบันทึกแบบถอดออกได้ไม่ได้เเม้านท์
+Comment[tr]=Bağlanmamış Ayrılabilir Ortam
+Comment[tt]=Totaşmağan Çığarulı Medium
+Comment[uk]=Демонтований переносний носій
+Comment[uz]=Ulanmagan saqlash uskunasi
+Comment[uz@cyrillic]=Уланмаган сақлаш ускунаси
+Comment[vi]=Ổ lưu trữ Di động đã gỡ ra
+Comment[wa]=Oiståve mediom dismonté
+Comment[zh_CN]=未挂载的可移动介质
+Comment[zh_TW]=未掛載的可攜式媒體
+Patterns=
+
+X-KDE-AutoEmbed=true
+X-KDE-IsAlso=inode/directory
diff --git a/kioslave/media/mimetypes/smb_mounted.desktop b/kioslave/media/mimetypes/smb_mounted.desktop
new file mode 100644
index 000000000..6f5bb0bff
--- /dev/null
+++ b/kioslave/media/mimetypes/smb_mounted.desktop
@@ -0,0 +1,83 @@
+[Desktop Entry]
+Icon=nfs_mount
+Type=MimeType
+MimeType=media/smb_mounted
+Comment=Mounted Samba (Microsoft Network) Share
+Comment[af]=Gekoppelde Samba (Microsoft Netwerk) Hulpbron
+Comment[ar]=مشاركة Samba محمّلة
+Comment[az]=Bağlanmış Samba (Microsoft Şəbəkəsi) Sahəsi
+Comment[be]=Прымацаваная агульная тэчка Samba (Сетка Microsoft)
+Comment[bg]=Монтиран ресурс Samba (Microsoft Network)
+Comment[bn]=মাউন্ট করা সাম্বা (মাইক্রোসফট নেটওয়ার্ক) শেয়ার
+Comment[br]=Rennad Samba (rouedad Microsoft) marc'het
+Comment[bs]=Montiran Samba (Microsoft Network) Share
+Comment[ca]=Recurs de Samba (xarxa Microsoft) muntat
+Comment[cs]=Připojený Samba (Microsoft Network) prostředek
+Comment[csb]=Zamòntowóné ùdzélenié Sambë (Microsoft Network)
+Comment[cy]=Cydranniad Samba (Rhwydwaith Microsoft) wedi'i osod
+Comment[da]=Monteret Samba-share (Microsoft-netværk)
+Comment[de]=Eingebundene Samba-Freigabe (Microsoft-Netzwerk)
+Comment[el]=Προσαρτημένος κοινόχρηστος πόρος Samba (Δίκτυο Microsoft)
+Comment[eo]=Surmetita Sambo-opuzaĵo
+Comment[es]=Recurso de Samba montado (Red de Microsoft)
+Comment[et]=Ühendatud Samba (Microsoft Network) ressurss
+Comment[eu]=Samba (Microsoft sarea) partekaketa muntatua
+Comment[fa]=مشترک Samba (Microsoft Network) سوار‌شده
+Comment[fi]=Liitetty Samba-jako (Microsoft-verkko)
+Comment[fr]=Partage Samba (réseau Microsoft) monté
+Comment[fy]=Oankeppele Samba-netwurkboarne (Microsoft-netwurken)
+Comment[ga]=Comhroinn Fheistithe Samba (Microsoft Network)
+Comment[gl]=Compartición Samba Montada (Rede de Microsoft)
+Comment[he]=שיתוף Microsoft Network) Samba) מחובר
+Comment[hi]=माउन्टेड साम्बा (माइक्रोसाफ्ट नेटवर्क) साझेदारी
+Comment[hr]=Pristupljeno Samba dijeljenje (Microsoft mreža)
+Comment[hsb]=Montowany Samba-(Microsoft syć)-zapisk
+Comment[hu]=Csatlakoztatott Samba-megosztás
+Comment[is]=Tengd Samba (Microsoft Network) sameign
+Comment[it]=Condivisione samba (Rete Microsoft) montata
+Comment[ja]=マウントされた Samba (マイクロソフトのネットワーク) 共有
+Comment[ka]=მონტირებული Samba რესურსი (Microsoft-ის ქსელი)
+Comment[kk]=Тіркеген Samba ресурсы (Microsoft желісі)
+Comment[km]=Samba (បណ្ដាញ Microsoft) Share បាន​រៀបចំ
+Comment[lt]=Sumontuotas Samba (Microsoft Network) bendro naudojimo diskas
+Comment[lv]=Piemontēta Samba (Microsoft tīkla) šāre
+Comment[mk]=Монтиран Samba заеднички ресурс (Microsoft мрежа)
+Comment[mn]=Залгагдсан Samba-Нөөцүүд (Microsoft-Сүлжээ)
+Comment[ms]=Perkongsian Samba Terlekap (Rangkaian Microsoft)
+Comment[mt]=Riżors Samba (Microsoft Network) immuntat
+Comment[nb]=Montert Samba-katalog (Microsoft nettverk)
+Comment[nds]=Inhangt Samba-Freegaav (Microsoft-Nettwark)
+Comment[ne]=माउन्ट गरिएको साम्बा (माइक्रो सफ्ट सञ्जाल) साझेदारी
+Comment[nl]=Aangekoppelde Samba-netwerkbron (Microsoft-netwerken)
+Comment[nn]=Montert Samba-ressurs (Microsoft-nettverk)
+Comment[nso]=Kabagano yeo e Nameleditswego ya Samba (Kgokagano ya Microsoft)
+Comment[pa]=ਮਾਊਟ ਕੀਤੀ ਸਾਂਬਾ (ਮਾਈਕਰੋਸਾਫਟ ਨੈੱਟਵਰਕ) ਸਾਂਝ
+Comment[pl]=Zamontowany udział Samby (sieci typu Microsoft Network)
+Comment[pt]=Partilha de Samba (Microsoft Network) montada
+Comment[pt_BR]=Compartilhamento do Samba (Rede Microsoft) montado
+Comment[ro]=Partajare Samba (rețea Microsoft) montată
+Comment[ru]=Смонтированный ресурс сети Microsoft
+Comment[rw]=Umugabane Samba (Urusobemiyoboro Microsoft) Washyizwemo
+Comment[se]=Čatnojuvvon Samba-resursa (Microsoft-fierbmi)
+Comment[sk]=Pripojený disk Samba (Microsoft Network)
+Comment[sl]=Priklopljen deljeni vir Sambe (Microsoftovo omrežje)
+Comment[sr]=Монтирано Samba дељење (Microsoft-ова мрежа)
+Comment[sr@Latn]=Montirano Samba deljenje (Microsoft-ova mreža)
+Comment[sv]=Monterad utdelad Samba-katalog (Microsoft-nätverk)
+Comment[ta]=சம்பா ஏற்றப்பட்டது (மைக்ரேசாப்ட் வலை) பகிர்வு
+Comment[tg]=Монтажшудаи манбаъи Samba (шабакаи Microsoft)
+Comment[th]=ทรัพยากร Samba (เครือข่ายวินโดว์ส) ที่ถูกเม้านท์
+Comment[tr]=Bağlanmış Samba (Microsoft Network) Paylaşımı
+Comment[tt]=Totaşqan Samba (Microsoft Çeltäre) Urtağı
+Comment[uk]=Змонтований спільний ресурс Samba (мережа Microsoft)
+Comment[ven]=Samba yo gonyaho (Vhukwamani ha Microsoft) U kovhekana
+Comment[vi]=Chia sẻ SAMBA (mạng của Microsoft) đã kết nối
+Comment[wa]=Pårtaedje Samba (Rantoele Microsoft) monté
+Comment[xh]=Samba Enyusiweyo (Umsebenzi womnatha we Microsoft) Ulwahlulo
+Comment[zh_CN]=挂载的 Samba (Microsoft 网络)共享
+Comment[zh_TW]=已掛載的 Samba (Microsoft 網路) 分享
+Comment[zu]=Isabelo se-Samba esinyusiwe (Uxhumano olusakazekile le-Network)
+Patterns=
+
+X-KDE-AutoEmbed=true
+X-KDE-IsAlso=inode/directory
diff --git a/kioslave/media/mimetypes/smb_unmounted.desktop b/kioslave/media/mimetypes/smb_unmounted.desktop
new file mode 100644
index 000000000..b59f063b2
--- /dev/null
+++ b/kioslave/media/mimetypes/smb_unmounted.desktop
@@ -0,0 +1,84 @@
+[Desktop Entry]
+Icon=nfs_unmount
+Type=MimeType
+MimeType=media/smb_unmounted
+Comment=Unmounted Samba (Microsoft Network) Share
+Comment[af]=Ontkoppelde Samba (Microsoft Netwerk) Hulpbron
+Comment[ar]=مشاركة Samba غير محمّلة
+Comment[az]=Ayrılmış Samba (Microsoft Şəbəkəsi) Sahəsi
+Comment[be]=Адмацаваная агульная тэчка Samba (Сетка Microsoft)
+Comment[bg]=Демонтиран ресурс Samba (Microsoft Network)
+Comment[bn]=আনমাউন্ট করা সাম্বা (মাইক্রোসফট নেটওয়ার্ক) শেয়ার
+Comment[br]=Rennad Samba (rouedad Microsoft) divarc'het
+Comment[bs]=Demontiran Samba (Microsoft Network) Share
+Comment[ca]=Recurs de Samba (xarxa Microsoft) desmuntat
+Comment[cs]=Odpojený Samba (Microsoft Network) prostředek
+Comment[csb]=Òdmòntowóné ùdzélenié Sambë (Microsoft Network)
+Comment[cy]=Cydranniad Samba (Rhwydwaith Microsoft) wedi'i ddadosod
+Comment[da]=Afmonteret Samba-share (Microsoft-netværk)
+Comment[de]=Nicht eingebundene Samba-Freigabe (Microsoft-Netzwerk)
+Comment[el]=Αποπροσαρτημένος κοινόχρηστος πόρος Samba (Δίκτυο Microsoft)
+Comment[eo]=Demetita Sambo-opuzaĵo
+Comment[es]=Recurso de Samba desmontado (Red de Microsoft)
+Comment[et]=Lahutatud Samba (Microsoft Network) ressurss
+Comment[eu]=Samba (Microsoft sarea) partekaketa desmuntatua
+Comment[fa]=مشترک Samba (Microsoft Network) پیاده‌شده
+Comment[fi]=Irrotettu Samba-jako (Microsoft-verkko)
+Comment[fr]=Partage Samba (réseau Microsoft) non monté
+Comment[fy]=Ofkeppele Samba-netwurkboarne (Microsoft-netwurken)
+Comment[ga]=Comhroinn Samba (Microsoft Network) Gan Fheistiú
+Comment[gl]=Compartición Samba Non Montada (Rede de Microsoft)
+Comment[he]=שיתוף Microsoft Network) Samba) מנותק
+Comment[hi]=अनमाउन्टेड साम्बा (माइक्रोसाफ्ट नेटवर्क) साझेदारी
+Comment[hr]=Nepristupljeno Samba dijeljenje (Microsoft mreža)
+Comment[hsb]=Njemontowany Samba-(Microsoft syć)-zapisk
+Comment[hu]=Leválasztott Samba-megosztás
+Comment[is]=Aftengd Samba (Microsoft Network) sameign
+Comment[it]=Condivisione samba (Rete Microsoft) non montata
+Comment[ja]=マウントされていない Samba (マイクロソフトのネットワーク) 共有
+Comment[ka]=დემონტირებული Samba რესურსი (Microsoft-ის ქსელი)
+Comment[kk]=Тіркеуден шығарған Samba ресурсы (Microsoft желісі)
+Comment[km]=Samba (បណ្ដាញ Microsoft) Share មិន​ទាន់​រៀបចំ
+Comment[lo]= ຫັງກາລີ
+Comment[lt]=Išmontuotas Samba (Microsoft Network) bendro naudojimo diskas
+Comment[lv]=Nomontēta Samba (Microsoft tīkla) šāre
+Comment[mk]=Одмонтиран Samba заеднички ресурс (Microsoft мрежа)
+Comment[mn]=Залгагдаагүй Samba-Нөөцүүд (Microsoft-Сүлжээ)
+Comment[ms]=Perkongsian Samba Nyahlekap (Rangkaian Microsoft)
+Comment[mt]=Riżors Samba (Microsoft Network) mhux immuntat
+Comment[nb]=Avmontert Samba-katalog (Microsoft nettverk)
+Comment[nds]=Afhangt Samba-Freegaav (Microsoft-Nettwark)
+Comment[ne]=अनमाउन्ट गरिएको साम्बा (माइक्रो सफ्ट सञ्जाल) साझेदारी
+Comment[nl]=Afgekoppelde Samba-netwerkbron (Microsoft-netwerkbron)
+Comment[nn]=Avmontert Samba-ressurs (Microsoft-nettverk)
+Comment[nso]=Kabagano yeo e Theositswego ya Samba (Kgokagano ya Microsoft)
+Comment[pa]=ਅਨਮਾਊਟ ਕੀਤੀ ਸਾਂਬਾ (ਮਾਈਕਰੋਸਾਫਟ ਨੈੱਟਵਰਕ) ਸਾਂਝ
+Comment[pl]=Odmontowany udział Samby (sieci typu Microsoft Network)
+Comment[pt]=Partilha de Samba (Microsoft Network) desmontada
+Comment[pt_BR]=Compartilhamento do Samba (Rede Microsoft) desmontado
+Comment[ro]=Partajare Samba (rețea Microsoft) nemontată
+Comment[ru]=Отмонтированный ресурс сети Microsoft
+Comment[rw]=Umugabane Samba (Urusobemiyoboro Microsoft) Wakuwemo
+Comment[se]=Gálgajuvvon Samba-resursa (Microsoft-fierbmi)
+Comment[sk]=Nepripojený disk Samba (Microsoft Network)
+Comment[sl]=Odklopljen deljeni vir Sambe (Microsoftovo omrežje)
+Comment[sr]=Демонтирано Samba дељење (Microsoft-ова мрежа)
+Comment[sr@Latn]=Demontirano Samba deljenje (Microsoft-ova mreža)
+Comment[sv]=Avmonterad utdelad Samba-katalog (Microsoft-nätverk)
+Comment[ta]=சம்பாவை வெளியேற்று(மைக்ரேசாப்ட் வலை) பகிர்வு
+Comment[tg]=Ҷудо шудаи манбаъи Samba (шабакаи Microsoft)
+Comment[th]=ทรัพยากร Samba (เครือข่ายวินโดว์ส) ที่ไม่ถูกเม้านท์
+Comment[tr]=Bağlanmış Samba (Microsoft Network) Paylaşımı
+Comment[tt]=Totaşmağan Samba (Microsoft Çeltäre) Urtağı
+Comment[uk]=Демонтований спільний ресурс Samba (мережа Microsoft)
+Comment[ven]=Samba i songo gonyaho (Vhukamani ha Microsoft) U kovhekana
+Comment[vi]=Chia sẻ SAMBA (mạng của Microsoft) đã gỡ ra
+Comment[wa]=Pårtaedje Samba (Rantoele Microsoft) dismonté
+Comment[xh]=Samba Enganyuswanga (Umsebenzi womnatha we Microsoft) Ulwahlulo
+Comment[zh_CN]=未挂载的 Samba (Microsoft 网络)共享
+Comment[zh_TW]=未掛載的 Samba (Microsoft 網路) 分享
+Comment[zu]=Isabelo se-Samba esehlisiwe (Uxhumano olusakazekile lwe-Microsoft)
+Patterns=
+
+X-KDE-AutoEmbed=true
+X-KDE-IsAlso=inode/directory
diff --git a/kioslave/media/mimetypes/svcd.desktop b/kioslave/media/mimetypes/svcd.desktop
new file mode 100644
index 000000000..68c965a6f
--- /dev/null
+++ b/kioslave/media/mimetypes/svcd.desktop
@@ -0,0 +1,50 @@
+[Desktop Entry]
+Type=MimeType
+MimeType=media/svcd
+Comment=Super Video CD
+Comment[ar]=قرص مدمج مرئي Super
+Comment[bg]=Супер VCD диск
+Comment[bn]=সুপার ভিডিও সিডি
+Comment[ca]=CD Súper Vídeo
+Comment[da]=Super Video-cd
+Comment[eo]=Supervidea lumdisko
+Comment[fa]=دیسک فشردۀ ابرویدیویی
+Comment[fr]=Super CD vidéo
+Comment[fy]=Super Fideo-kompaktskiif
+Comment[gl]=Super Vídeo CD
+Comment[hi]=सुपर वीडियो सीडी
+Comment[hu]=Super Video-CD
+Comment[is]=Súper vídeó CD
+Comment[it]=Super video CD
+Comment[ja]=スーパービデオ CD
+Comment[ka]=სუპერ ვიდეო CD
+Comment[km]=ស៊ីឌី​វីដេអូ​គុណភាព​ខ្ពស់
+Comment[mk]=Супер видео ЦД
+Comment[ms]=CD Supervideo
+Comment[nb]=Super video CD
+Comment[nds]=Super-Video-CD
+Comment[ne]=सुपर भिडियो सीडी
+Comment[nl]=Super Video-cd
+Comment[nn]=Super Video-CD
+Comment[pa]=ਸੁਪਰ ਵੀਡਿਓ CD
+Comment[pl]=Płyta Super Video CD
+Comment[pt]=Super Vídeo CD
+Comment[pt_BR]=Super vídeo CD (SVCD)
+Comment[ro]=CD Super Video
+Comment[rw]=CD Videwo Ihebuje
+Comment[sr]=Супер видео CD
+Comment[sr@Latn]=Super video CD
+Comment[sv]=Supervideo-cd
+Comment[ta]=சூப்பர் படக்காட்சி குறுந்தகடு
+Comment[te]=సూపర్ విడియొ సిడి
+Comment[tg]=Супер Видео CD
+Comment[th]=ซุเปอร์วิดีโอซีดี
+Comment[tr]=Süper Video CD'si
+Comment[uk]=Супер відео КД
+Comment[uz]=Super-video kompakt-disk
+Comment[uz@cyrillic]=Супер-видео компакт-диск
+Comment[vi]=Đĩa siêu video CD
+Comment[wa]=Super plake lazer CD videyo
+Comment[zh_CN]=超级 VCD
+Comment[zh_TW]=超級視訊 CD
+Icon=cdrom_unmount
diff --git a/kioslave/media/mimetypes/vcd.desktop b/kioslave/media/mimetypes/vcd.desktop
new file mode 100644
index 000000000..dae4ddcaf
--- /dev/null
+++ b/kioslave/media/mimetypes/vcd.desktop
@@ -0,0 +1,50 @@
+[Desktop Entry]
+Type=MimeType
+MimeType=media/vcd
+Comment=Video CD
+Comment[ar]=قرص مدمج مرئي
+Comment[bg]=VCD диск
+Comment[bn]=ভিডিও সিডি
+Comment[br]=CD Video
+Comment[ca]=CD Vídeo
+Comment[da]=Video-cd
+Comment[el]=Βίντεο CD
+Comment[eo]=Video-LD
+Comment[fa]=دیسک فشردۀ ویدیویی
+Comment[fr]=CD vidéo
+Comment[fy]=Fideo-kompaktskiif
+Comment[ga]=Dlúthdhiosca Físe
+Comment[gl]=Vídeo CD
+Comment[hi]=वीडियो सीडी
+Comment[hu]=Video-CD
+Comment[is]=Vídeó CD
+Comment[ja]=ビデオ CD
+Comment[kk]=Бейне CD
+Comment[km]=ស៊ីឌី​វីដេអូ
+Comment[mk]=Видео ЦД
+Comment[ms]=CD Video
+Comment[nds]=Video-CD
+Comment[ne]=भिडियो सीडी
+Comment[nl]=Video-cd
+Comment[nn]=Video-CD
+Comment[pa]=ਵੀਡਿਓ CD
+Comment[pl]=Płyta Video CD
+Comment[pt]=Vídeo CD
+Comment[pt_BR]=Vídeo CD (VCD)
+Comment[ro]=CD Video
+Comment[rw]=CD Videwo
+Comment[sr]=Видео CD
+Comment[sv]=Video-cd
+Comment[ta]=படக்காட்சி குறுந்தகடு
+Comment[te]=విడియొ సిడి
+Comment[tg]=Видео CD
+Comment[th]=วิดีโอซีดี
+Comment[tr]=Video CD'si
+Comment[uk]=Відео КД
+Comment[uz]=Video kompakt-disk
+Comment[uz@cyrillic]=Видео компакт-диск
+Comment[vi]=Đĩa video CD
+Comment[wa]=Plake lazer CD videyo
+Comment[zh_CN]=VCD
+Comment[zh_TW]=視訊 CD
+Icon=cdrom_unmount
diff --git a/kioslave/media/mimetypes/zip_mounted.desktop b/kioslave/media/mimetypes/zip_mounted.desktop
new file mode 100644
index 000000000..3a9f97d30
--- /dev/null
+++ b/kioslave/media/mimetypes/zip_mounted.desktop
@@ -0,0 +1,85 @@
+[Desktop Entry]
+Icon=zip_mount
+Type=MimeType
+MimeType=media/zip_mounted
+Comment=Mounted Zip Disk
+Comment[af]=Gekoppelde Zip Disket
+Comment[ar]=قرص Zip محمّل
+Comment[az]=Bağlanmış Zip Disk
+Comment[be]=Прымацаваны дыск Zip
+Comment[bg]=Монтиран Zip диск
+Comment[bn]=মাউন্ট করা জিপ (Zip) ডিস্ক
+Comment[br]=Pladenn Zip marc'het
+Comment[bs]=Montiran Zip disk
+Comment[ca]=Disc Zip muntat
+Comment[cs]=Připojený disk Zip
+Comment[csb]=Zamòntowóny disk Zip
+Comment[cy]=Disg Zip wedi'i osod
+Comment[da]=Monteret zip-disk
+Comment[de]=Eingebundenes Zip-Medium
+Comment[el]=Προσαρτημένος δίσκος Zip
+Comment[eo]=Surmetita ZIP-disko
+Comment[es]=Disco Zip montado
+Comment[et]=Ühendatud Zip-ketas
+Comment[eu]=Zip diska muntatua
+Comment[fa]=دیسک فشردۀ سوارشده
+Comment[fi]=Liitetty Zip-levy
+Comment[fr]=Disque Zip monté
+Comment[fy]=Oankeppelee Zip-skiif
+Comment[ga]=Diosca Zip feistithe
+Comment[gl]=Disco Zip Montado
+Comment[he]=תקליטון Zip מחובר
+Comment[hi]=माउन्टेड जिप डिस्क
+Comment[hr]=Pristupljeni Zip disk
+Comment[hu]=Csatlakoztatott Zip-lemez
+Comment[is]=Tengdur Zip diskur
+Comment[it]=Disco Zip montato
+Comment[ja]=マウントされた Zip ディスク
+Comment[ka]=მონტირებული диск Zip
+Comment[kk]=Тіркеген Zip дискі
+Comment[km]=ថាស Zip បាន​រៀបចំ
+Comment[lo]=ຈໍພາບ
+Comment[lt]=Sumontuotas Zip diskas
+Comment[lv]=Piemontēts Zip disks
+Comment[mk]=Монтиран Зип-диск
+Comment[mn]=Залгагдсан Zip-Диск
+Comment[ms]=Cakera Zip Terlekap
+Comment[mt]=Diska Zip immuntata
+Comment[nb]=Montert Zip-disk
+Comment[nds]=Inhangt Zip-Diskett
+Comment[ne]=माउन्ट गरिएको जिप डिस्क
+Comment[nl]=Aangekoppelde Zip-diskette
+Comment[nn]=Montert Zip-disk
+Comment[nso]=Disk yeo e Nameleditswego ya ZIP
+Comment[pa]=ਮਾਊਟ ਕੀਤੀ ਜਿਪ ਡਿਸਕ
+Comment[pl]=Zamontowana dyskietka Zip
+Comment[pt]=Disco ZIP montado
+Comment[pt_BR]=Disco Zip Montado
+Comment[ro]=Disc ZIP montat
+Comment[ru]=Смонтированный диск Zip
+Comment[rw]=Disiki Zipu Yashyizwemo
+Comment[se]=Čatnojuvvon Zip-skearru
+Comment[sk]=Pripojený disk Zip
+Comment[sl]=Priklopljen disk Zip
+Comment[sr]=Монтиран Zip диск
+Comment[sr@Latn]=Montiran Zip disk
+Comment[sv]=Monterad Zip-diskett
+Comment[ta]=இறக்கப்பட்ட சுருக்க வட்டு
+Comment[tg]=Монтажшудаи диски Zip
+Comment[th]=ดิสก์ Zip ที่ถูกเม้านท์
+Comment[tr]=Bağlı Zip Diski
+Comment[tt]=Totaşqan Zip Disk
+Comment[uk]=Змонтований диск Zip
+Comment[uz]=Ulangan ZIP-disk
+Comment[uz@cyrillic]=Уланган ZIP-диск
+Comment[ven]=Disk ya Zip yo gonyiswaho
+Comment[vi]=Đĩa ZIP đã kết nối
+Comment[wa]=Plakete ZIP montêye
+Comment[xh]=Diski Yoqokelelo ndawonye Kwediski
+Comment[zh_CN]=挂载的 Zip 磁盘
+Comment[zh_TW]=已掛載的 Zip 磁碟
+Comment[zu]=I-disk yokuhlanganiselwe ndawonye eyenyusiwe
+Patterns=
+
+X-KDE-AutoEmbed=true
+X-KDE-IsAlso=inode/directory
diff --git a/kioslave/media/mimetypes/zip_unmounted.desktop b/kioslave/media/mimetypes/zip_unmounted.desktop
new file mode 100644
index 000000000..784fde7e4
--- /dev/null
+++ b/kioslave/media/mimetypes/zip_unmounted.desktop
@@ -0,0 +1,85 @@
+[Desktop Entry]
+Icon=zip_unmount
+Type=MimeType
+MimeType=media/zip_unmounted
+Comment=Unmounted Zip Disk
+Comment[af]=Ontkoppel Zip Disket
+Comment[ar]=قرص Zip غير محمّل
+Comment[az]=Ayrılmış Zip Disk
+Comment[be]=Адмацаваны дыск Zip
+Comment[bg]=Демонтиран Zip диск
+Comment[bn]=আনমাউন্ট করা জিপ (Zip) ডিস্ক
+Comment[br]=Pladenn Zip divountet
+Comment[bs]=Demontiran Zip disk
+Comment[ca]=Disc Zip desmuntat
+Comment[cs]=Odpojený disk Zip
+Comment[csb]=Òdmòntowóny disk Zip
+Comment[cy]=Disg Zip wedi'i ddadosod
+Comment[da]=Afmonteret zip-disk
+Comment[de]=Nicht eingebundenes Zip-Medium
+Comment[el]=Αποπροσαρτημένος δίσκος Zip
+Comment[eo]=Demetita ZIP-disko
+Comment[es]=Disco Zip desmontado
+Comment[et]=Lahutatud Zip-ketas
+Comment[eu]=Zip diska desmuntatua
+Comment[fa]=دیسک فشردۀ پیاده‌شده
+Comment[fi]=Irrotettu Zip-levy
+Comment[fr]=Disque Zip non monté
+Comment[fy]=Ofkeppele Zip-skiif
+Comment[ga]=Diosca Zip neamhfheistithe
+Comment[gl]=Disco Zip non Montado
+Comment[he]=תקליטון Zip מנותק
+Comment[hi]=अनमाउन्टेड जिप डिस्क
+Comment[hr]=Nepristupljeni Zip disk
+Comment[hu]=Leválasztott Zip-lemez
+Comment[is]=Aftengdur Zip diskur
+Comment[it]=Disco Zip non montato
+Comment[ja]=マウントされていない Zip ディスク
+Comment[ka]=დემონტირებული диск Zip
+Comment[kk]=Тіркеуден шығарған Zip дискі
+Comment[km]=ថាស Zip មិន​បាន​រៀបចំ
+Comment[lo]= ຫັງກາລີ
+Comment[lt]=Išmontuotas Zip diskas
+Comment[lv]=Nomontēts Zip disks
+Comment[mk]=Одмонтиран Зип-диск
+Comment[mn]=Салгагдсан Zip-Диск
+Comment[ms]=Cakera Zip Nyahlekap
+Comment[mt]=Diska Zip mhux immuntata
+Comment[nb]=Avmontert Zip-disk
+Comment[nds]=Afhangt Zip-Diskett
+Comment[ne]=अनमाउन्ट गरिएको जिप डिस्क
+Comment[nl]=Afgekoppelde Zip-diskette
+Comment[nn]=Avmontert Zip-disk
+Comment[nso]=Disk yeo e Theositswego ya ZIP
+Comment[pa]=ਅਨਮਾਊਟ ਕੀਤੀ ਜ਼ਿਪ ਡਿਸਕ
+Comment[pl]=Odmontowana dyskietka Zip
+Comment[pt]=Disco ZIP desmontado
+Comment[pt_BR]=Disco Zip Desmontado
+Comment[ro]=Disc ZIP nemontat
+Comment[ru]=Отмонтированный диск Zip
+Comment[rw]=Disiki Zipu Yakuwemo
+Comment[se]=Gálgajuvvon Zip-skearru
+Comment[sk]=Nepripojený disk Zip
+Comment[sl]=Odklopljen disk Zip
+Comment[sr]=Демонтиран Zip диск
+Comment[sr@Latn]=Demontiran Zip disk
+Comment[sv]=Avmonterad Zip-diskett
+Comment[ta]=வெளியேற்றிய சுருக்க தகடு
+Comment[tg]=Ҷудо шудаи диски Zip
+Comment[th]=ดิสก์ Zip ที่ไม่ได้เม้านท์
+Comment[tr]=Ayrılmış Zip Diski
+Comment[tt]=Totaşmağan Zip Disk
+Comment[uk]=Демонтований диск Zip
+Comment[uz]=Ulanmagan ZIP-disk
+Comment[uz@cyrillic]=Уланмаган ZIP-диск
+Comment[ven]=Disk ya Zip i songo gonyiswaho
+Comment[vi]=Đĩa ZIP đã gỡ ra
+Comment[wa]=Plakete ZIP dismontêye
+Comment[xh]=Diski Yoqokelelo ndawone Enganyuswanga
+Comment[zh_CN]=挂载的 Zip 磁盘
+Comment[zh_TW]=未掛載的 Zip 磁碟
+Comment[zu]=I-disk yokuhlanganiselwe ndawonye eyehlisiwe
+Patterns=
+
+X-KDE-AutoEmbed=true
+X-KDE-IsAlso=inode/directory
diff --git a/kioslave/media/mounthelper/Makefile.am b/kioslave/media/mounthelper/Makefile.am
new file mode 100644
index 000000000..9080ba81a
--- /dev/null
+++ b/kioslave/media/mounthelper/Makefile.am
@@ -0,0 +1,12 @@
+bin_PROGRAMS = kio_media_mounthelper
+
+INCLUDES = -I$(srcdir)/../libmediacommon $(all_includes)
+AM_LDFLAGS = $(all_libraries)
+
+kio_media_mounthelper_SOURCES = kio_media_mounthelper.cpp
+
+kio_media_mounthelper_LDFLAGS = $(KDE_RPATH) $(all_libraries)
+kio_media_mounthelper_LDADD = ../libmediacommon/libmediacommon.la $(LIB_KIO)
+
+METASOURCES = AUTO
+
diff --git a/kioslave/media/mounthelper/kio_media_mounthelper.cpp b/kioslave/media/mounthelper/kio_media_mounthelper.cpp
new file mode 100644
index 000000000..12743847f
--- /dev/null
+++ b/kioslave/media/mounthelper/kio_media_mounthelper.cpp
@@ -0,0 +1,209 @@
+/* This file is part of the KDE project
+ Copyright (c) 2004 Kévin Ottens <ervin ipsquad net>
+ Parts of this file are
+ Copyright 2003 Waldo Bastian <bastian@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <kcmdlineargs.h>
+#include <klocale.h>
+#include <kapplication.h>
+#include <kurl.h>
+#include <kmessagebox.h>
+#include <dcopclient.h>
+#include <dcopref.h>
+#include <qtimer.h>
+#include <stdlib.h>
+#include <kdebug.h>
+#include <kglobal.h>
+#include <kprocess.h>
+#include <kstartupinfo.h>
+
+#include "kio_media_mounthelper.h"
+
+const Medium MountHelper::findMedium(const KURL &url)
+{
+ DCOPRef mediamanager("kded", "mediamanager");
+
+ // Try filename first
+ DCOPReply reply = mediamanager.call( "properties", url.fileName() );
+ if ( !reply.isValid() ) {
+ m_errorStr = i18n("The KDE mediamanager is not running.")+"\n";
+ return Medium(QString::null, QString::null);
+ }
+ const Medium& medium = Medium::create(reply);
+ if ( medium.id().isEmpty() ) {
+ // Try full URL now
+ reply = mediamanager.call( "properties", url.prettyURL() );
+ if ( !reply.isValid() ) {
+ m_errorStr = i18n("Internal Error");
+ return Medium(QString::null, QString::null);
+ }
+ return Medium::create(reply);
+ } else {
+ return medium;
+ }
+}
+
+MountHelper::MountHelper() : KApplication()
+{
+ KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
+
+ m_errorStr = "";
+
+ KURL url(args->url(0));
+ const Medium medium = findMedium(url);
+
+ if ( medium.id().isEmpty() )
+ {
+ if (m_errorStr.isEmpty())
+ m_errorStr+= i18n("%1 cannot be found.").arg(url.prettyURL());
+ QTimer::singleShot(0, this, SLOT(error()) );
+ return;
+ }
+
+ if ( !medium.isMountable() && !args->isSet("e") && !args->isSet("s"))
+ {
+ m_errorStr = i18n("%1 is not a mountable media.").arg(url.prettyURL());
+ QTimer::singleShot(0, this, SLOT(error()) );
+ return;
+ }
+
+ QString device = medium.deviceNode();
+ QString mount_point = medium.mountPoint();
+
+ m_isCdrom = medium.mimeType().find("dvd")!=-1
+ || medium.mimeType().find("cd")!=-1;
+
+ if (args->isSet("u"))
+ {
+ DCOPRef mediamanager("kded", "mediamanager");
+ DCOPReply reply = mediamanager.call( "unmount", medium.id());
+ if (reply.isValid())
+ reply.get(m_errorStr);
+ kdDebug() << "medium unmount " << m_errorStr << endl;
+ if (m_errorStr.isNull())
+ ::exit(0);
+ else
+ error();
+ }
+ else if (args->isSet("s") || args->isSet("e"))
+ {
+ /*
+ * We want to call mediamanager unmount before invoking eject. That's
+ * because unmount would provide an informative error message in case of
+ * failure. However, there are cases when unmount would fail
+ * (supermount, slackware, see bug#116209) but eject would succeed.
+ * Thus if unmount fails, save unmount error message and invokeEject()
+ * anyway. Only if both unmount and eject fail, notify the user by
+ * displaying the saved error message (see ejectFinished()).
+ */
+ if (medium.isMounted())
+ {
+ DCOPRef mediamanager("kded", "mediamanager");
+ DCOPReply reply = mediamanager.call( "unmount", medium.id());
+ if (reply.isValid())
+ reply.get(m_errorStr);
+ if (m_errorStr.isNull())
+ invokeEject(device, true);
+ else
+ error();
+ m_device = device;
+ } else
+ invokeEject(device, true);
+ }
+ else
+ {
+ DCOPRef mediamanager("kded", "mediamanager");
+ DCOPReply reply = mediamanager.call( "mount", medium.id());
+ if (reply.isValid())
+ reply.get(m_errorStr);
+ if (m_errorStr.isNull())
+ ::exit(0);
+ else
+ error();
+ }
+}
+
+void MountHelper::invokeEject(const QString &device, bool quiet)
+{
+ KProcess *proc = new KProcess(this);
+ *proc << "kdeeject";
+ if (quiet)
+ {
+ *proc << "-q";
+ }
+ *proc << device;
+ connect( proc, SIGNAL(processExited(KProcess *)),
+ this, SLOT( ejectFinished(KProcess *) ) );
+ proc->start();
+}
+
+void MountHelper::ejectFinished(KProcess* proc)
+{
+ /*
+ * If eject failed, report the error stored in m_errorStr
+ */
+ if (proc->normalExit() && proc->exitStatus() == 0) {
+ ::exit(0);
+ } else {
+ if (m_errorStr.isEmpty()) {
+ if (m_isCdrom)
+ m_errorStr = i18n("The device was successfully unmounted, but the tray could not be opened");
+ else
+ m_errorStr = i18n("The device was successfully unmounted, but could not be ejected");
+ }
+ QTimer::singleShot(0, this, SLOT(error()));
+ }
+}
+
+void MountHelper::error()
+{
+ KMessageBox::error(0, m_errorStr);
+ ::exit(1);
+}
+
+static KCmdLineOptions options[] =
+{
+ { "u", I18N_NOOP("Unmount given URL"), 0 },
+ { "m", I18N_NOOP("Mount given URL (default)"), 0 },
+ { "e", I18N_NOOP("Eject given URL via kdeeject"), 0},
+ { "s", I18N_NOOP("Unmount and Eject given URL (necessary for some USB devices)"), 0},
+ {"!+URL", I18N_NOOP("media:/ URL to mount/unmount/eject/remove"), 0 },
+ KCmdLineLastOption
+};
+
+
+int main(int argc, char **argv)
+{
+ KCmdLineArgs::init(argc, argv, "kio_media_mounthelper",
+ "kio_media_mounthelper", "kio_media_mounthelper",
+ "0.1");
+
+ KCmdLineArgs::addCmdLineOptions( options );
+ KGlobal::locale()->setMainCatalogue("kio_media");
+ KApplication::addCmdLineOptions();
+
+ if (KCmdLineArgs::parsedArgs()->count()==0) KCmdLineArgs::usage();
+ KApplication *app = new MountHelper();
+
+ KStartupInfo::appStarted();
+ app->dcopClient()->attach();
+ return app->exec();
+}
+
+#include "kio_media_mounthelper.moc"
diff --git a/kioslave/media/mounthelper/kio_media_mounthelper.h b/kioslave/media/mounthelper/kio_media_mounthelper.h
new file mode 100644
index 000000000..478d802f9
--- /dev/null
+++ b/kioslave/media/mounthelper/kio_media_mounthelper.h
@@ -0,0 +1,49 @@
+/* This file is part of the KDE project
+ Copyright (c) 2004 Kvin Ottens <ervin ipsquad net>
+ Parts of this file are
+ Copyright 2003 Waldo Bastian <bastian@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef _KIO_MEDIA_MOUNTHELPER_H_
+#define _KIO_MEDIA_MOUNTHELPER_H_
+
+#include <kapplication.h>
+#include <qstring.h>
+#include <kio/job.h>
+
+#include "medium.h"
+
+class MountHelper : public KApplication
+{
+ Q_OBJECT
+public:
+ MountHelper();
+
+private:
+ const Medium findMedium(const KURL &url);
+ void invokeEject(const QString &device, bool quiet=false);
+ QString m_errorStr;
+ QString m_device;
+ bool m_isCdrom;
+
+private slots:
+ void ejectFinished(KProcess* proc);
+ void error();
+};
+
+#endif
diff --git a/kioslave/media/propsdlgplugin/Makefile.am b/kioslave/media/propsdlgplugin/Makefile.am
new file mode 100644
index 000000000..5e3d8af83
--- /dev/null
+++ b/kioslave/media/propsdlgplugin/Makefile.am
@@ -0,0 +1,12 @@
+METASOURCES = AUTO
+
+kde_module_LTLIBRARIES = media_propsdlgplugin.la
+
+media_propsdlgplugin_la_LIBADD = ../libmediacommon/libmediacommon.la $(LIB_KIO)
+media_propsdlgplugin_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN)
+
+AM_CPPFLAGS = $(all_includes)
+
+kde_services_DATA = media_propsdlgplugin.desktop
+
+media_propsdlgplugin_la_SOURCES = propertiespage.cpp propertiespagegui.ui propsdlgshareplugin.cpp
diff --git a/kioslave/media/propsdlgplugin/media_propsdlgplugin.desktop b/kioslave/media/propsdlgplugin/media_propsdlgplugin.desktop
new file mode 100644
index 000000000..c0cdcbbba
--- /dev/null
+++ b/kioslave/media/propsdlgplugin/media_propsdlgplugin.desktop
@@ -0,0 +1,102 @@
+[Desktop Entry]
+Type=Service
+Name=Media Properties Page
+Name[bg]=Страница с информация за носителя
+Name[bn]=মিডিয়া বৈশিষ্ট্যাবলী পৃষ্ঠা
+Name[ca]=Pàgina de propietats de suport
+Name[cs]=Stránka vlastností média
+Name[csb]=Starna swòjiznë media
+Name[da]=Medieegenskabsside
+Name[de]=Eigenschaften von Medien
+Name[el]=Σελίδα ιδιοτήτων μέσων
+Name[eo]=Medio-Ecoj Paĝo
+Name[es]=Página de propiedades de medios
+Name[et]=Andmekandjate omadused
+Name[fa]=صفحۀ ویژگیهای رسانه
+Name[fi]=Mediaominaisuudet
+Name[fr]=Page de propriétés du média
+Name[fy]=Media eigenskip side
+Name[gl]=Páxina de Propiedades dos Media
+Name[he]=דף מאפייני מדיה
+Name[hr]=Stranica svojstva medija
+Name[hu]=Médiajellemzők lap
+Name[is]=Eiginleikar miðils
+Name[it]=Pagina delle proprietà dei dispositivi di archiviazione
+Name[ja]=メディア属性ページ
+Name[kk]=Медиа қасиеттер беті
+Name[km]=ទំព័រ​លក្ខណៈសម្បត្តិ​មេឌៀ
+Name[lt]=Media įrenginio savybių puslapis
+Name[nb]=Side for medievarsling
+Name[nds]=Medienegenschappen-Siet
+Name[ne]=मिडिया विशेषता पृष्ठ
+Name[nl]=Pagina met media-eigenschappen
+Name[nn]=Side for medieeigenskapar
+Name[pa]=ਮੀਡਿਆ ਵਿਸ਼ੇਸ਼ਤਾ ਸਫ਼ਾ
+Name[pl]=Strona właściwości nośnika
+Name[pt]=Página de Propriedades de Suportes Físicos
+Name[pt_BR]=Página de Propriedades da Mídia
+Name[ro]=Pagina de proprietăți media
+Name[ru]=Свойства диска
+Name[sk]=Strana vlastností média
+Name[sl]=Stran z lastnostmi nosilca
+Name[sr]=Страна са својствима медијума
+Name[sr@Latn]=Strana sa svojstvima medijuma
+Name[sv]=Sida för mediaegenskaper
+Name[te]=మాధ్యమ గుణాల పుట
+Name[th]=หน้าคุณสมบัติของสื่อ
+Name[tr]=Ortam Özellikleri Sayfası
+Name[uk]=Сторінка властивостей носіїв інформації
+Name[uz]=Saqlash uskunalarning xossalari
+Name[uz@cyrillic]=Сақлаш ускуналарнинг хоссалари
+Name[vi]=Trang tài sản phương tiện
+Name[wa]=Pådje des prôpietés media
+Name[zh_CN]=介质属性页面
+Name[zh_TW]=媒體內容頁
+Comment=Konqueror properties dialog plugin to configure mount behaviour
+Comment[bg]=Приставка за настройване на монтирането (Konqueror)
+Comment[ca]=Diàleg de propietats de l'endollable Konqueror per a configurar el comportament de muntatge
+Comment[cs]=Dialog nastavení chování připojení modulu pro Konqueror
+Comment[csb]=Plugins òkna swòjiznë Konquerora do kònfigùracëji zachówaniô mòntowaniô
+Comment[da]=Konqueror plugin med egenskabsdialog til at indstille monteringsopførsel
+Comment[de]=Konqueror-Modul zum Einstellen des Verhaltens beim Einbinden
+Comment[el]=Πρόσθετο διαλόγου ιδιοτήτων του Konqueror για τη ρύθμιση της συμπεριφοράς προσάρτησης
+Comment[eo]=Konkeranto eco-dialogo kromaĵo por agordi surmeto-konduton
+Comment[es]=Complemento de la ventana de propiedades de Konqueror para configurar el comportamiento del montaje
+Comment[et]=Konquerori seadistustedialoogi plugin andmekandjate ühendamise seadistamiseks
+Comment[fa]=وصلۀ محاورۀ ویژگیهای Konqueror برای پیکربندی رفتار سوار کردن
+Comment[fi]=Konquerorin ominaisuussovelma, joka tarkkailee liitospisteitä
+Comment[fr]=Module de Konqueror pour configurer le comportement du montage
+Comment[fy]=Konqueror eigenskip-dialooch-plugin om keppelgedrach te konfigurearjen
+Comment[gl]=Extensión de diálogo de propiedades para Konqueror para configurar o comportamento das montaxes
+Comment[he]=תוסף חלון מאפיינים של Konqueror לקביעת אפשרויות חיבור
+Comment[hr]=Konqueror dodatak dijaloga svojstava za konfiguriranje načina pristupanja
+Comment[hu]=Konqueror beállítómodul a csatlakoztatási mód megadásához
+Comment[is]=Konqueror eiginleikagluggi til að stilla tengihegðun
+Comment[it]=Plugin della configurazione di Konqueror per configurare il montaggio
+Comment[ja]=mount の挙動を設定する Konqueror プロパティダイアログ プラグイン
+Comment[kk]=Жалғау тәртібін баптайтын Konqueror қасиеттер диалогының плагин модулі
+Comment[km]=កម្មវិធី​ជំនួយ​ឲ្យ​មាន​ប្រអប់​លក្ខណៈសម្បត្តិ Konqueror ដើម្បី​កំណត់​រចនាសម្ព័ន្ធ​ឥរិយាបថ​ម៉ោន
+Comment[lt]=Konqueror savybių dialogo priedas, leidžiantis konfigūruoti montavimo elgseną
+Comment[nb]=Et programtillegg for å sette opp montering av enheter i Konqueror
+Comment[nds]=Egenschappendialoog-Plugin för Konqueror för't Instellen vun't Inhangbedregen
+Comment[ne]=माउन्ट व्यवहार कन्फिगर गर्न कन्क्वेरर विशेषता संवाद प्लगइन
+Comment[nl]=Dialoogvenster voor Konqueror om het aankoppelgedrag in te stellen
+Comment[nn]=Programtillegg for oppsett av montering i Konqueror
+Comment[pl]=Wtyczka okna właściwości Konquerora do konfiguracji zachowania montowania
+Comment[pt]='Plugin' da janela de propriedades do Konqueror, para configurar o comportamento da montagem
+Comment[pt_BR]=Plug-in do diálogo de propriedades do Konqueror para configurar o comportamento da montagem
+Comment[ro]=Plugin de dialog al proprietăților Konqueror pentru a configura comportarea lui mount
+Comment[ru]=Модуль свойств для Konqueror, отвечающий за поведение при подключении файловых систем
+Comment[sk]=Modul Konqueror dialógu vlastností pre konfiguráciu správania pripojenia
+Comment[sl]=Vstavek za Konqueror s katerim se nastavlja obnašanje priklopa medijev
+Comment[sr]=Прикључак са својствима Konqueror-а за подешавање понашања при монтирању
+Comment[sr@Latn]=Priključak sa svojstvima Konqueror-a za podešavanje ponašanja pri montiranju
+Comment[sv]=Konqueror insticksprogram med egenskapsdialogruta för att anpassa monteringsbeteende
+Comment[th]=ปลั๊กอินกล่องตอบโต้ของ Konqueror ใช้เพื่อปรับแต่งพฤติกรรมการเมานท์สื่อ
+Comment[uk]=Втулок вікна властивостей Konqueror для налаштування поведінки монтування
+Comment[vi]=bổ sung hộp thoại tài sản Konqueror để cấu hình ứng xử gắn kết
+Comment[wa]=Tchôke-divins di dvize di prôpietés Konqueror po-z apontyî l' dujhance do montaedje
+Comment[zh_CN]=配置挂载行为的 Konqueror 属性对话框插件
+Comment[zh_TW]=Konqueror 內容對話框外掛程式,用於設定掛載的行為
+X-KDE-Library=media_propsdlgplugin
+ServiceTypes=KPropsDlg/Plugin,media/audiocd,media/hdd_mounted,media/hdd_unmounted,media/cdrom_mounted,media/cdrom_unmounted,media/cdwriter_mounted,media/nfs_mounted,media/cdwriter_unmounted,media/nfs_unmounted,media/removable_mounted,media/dvd_mounted,media/removable_unmounted,media/dvd_unmounted,media/smb_mounted,media/dvdvideo,media/smb_unmounted,media/floppy5_mounted,media/floppy5_unmounted,media/floppy_mounted,media/zip_mounted,media/floppy_unmounted,media/zip_unmounted,media/camera_mounted,media/camera_unmounted
diff --git a/kioslave/media/propsdlgplugin/propertiespage.cpp b/kioslave/media/propsdlgplugin/propertiespage.cpp
new file mode 100644
index 000000000..fd1c098e0
--- /dev/null
+++ b/kioslave/media/propsdlgplugin/propertiespage.cpp
@@ -0,0 +1,217 @@
+/*
+ Copyright (c) 2004 Jan Schaefer <j_schaef@informatik.uni-kl.de>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include <qcheckbox.h>
+#include <qtooltip.h>
+#include <qbuttongroup.h>
+#include <qlineedit.h>
+#include <qfileinfo.h>
+#include <qlabel.h>
+#include <qregexp.h>
+#include <kpushbutton.h>
+#include <kmessagebox.h>
+#include <klocale.h>
+#include <qcombobox.h>
+#include <qtimer.h>
+#include <kdebug.h>
+#include "propertiespage.h"
+#include <dcopref.h>
+
+// keep in sync with .ui and kded module
+const char *short_names[] = {"lower", "win95", "winnt", "mixed", 0 };
+const char *journales[] = {"data", "ordered", "writeback", 0 };
+
+PropertiesPage::PropertiesPage(QWidget* parent, const QString &_id)
+ : PropertiesPageGUI(parent), id(_id)
+{
+ kdDebug() << "props page " << id << endl;
+ DCOPRef mediamanager("kded", "mediamanager");
+ DCOPReply reply = mediamanager.call( "mountoptions", id);
+
+ QStringList list;
+
+ if (reply.isValid())
+ list = reply;
+
+ if (list.size()) {
+ kdDebug() << "list " << list << endl;
+
+ for (QStringList::ConstIterator it = list.begin(); it != list.end(); ++it)
+ {
+ QString key = (*it).left((*it).find('='));
+ QString value = (*it).mid((*it).find('=') + 1);
+ kdDebug() << "key '" << key << "' value '" << value << "'\n";
+ options[key] = value;
+ }
+
+ if (!options.contains("ro"))
+ option_ro->hide();
+ else
+ option_ro->setChecked(options["ro"] == "true");
+ connect( option_ro, SIGNAL( stateChanged(int) ), SIGNAL( changed() ) );
+
+ if (!options.contains("quiet"))
+ option_quiet->hide();
+ else
+ option_quiet->setChecked(options["quiet"] == "true");
+ connect( option_quiet, SIGNAL( stateChanged(int) ), SIGNAL( changed() ) );
+
+ if (!options.contains("sync"))
+ option_sync->hide();
+ else
+ option_sync->setChecked(options["sync"] == "true");
+ connect( option_sync, SIGNAL( stateChanged(int) ), SIGNAL( changed() ) );
+
+ if (!options.contains("atime"))
+ option_atime->hide();
+ else
+ option_atime->setChecked(options["atime"] == "true");
+ connect( option_atime, SIGNAL( stateChanged(int) ), SIGNAL( changed() ) );
+
+ if (!options.contains("flush"))
+ option_flush->hide();
+ else
+ option_flush->setChecked(options["flush"] == "true");
+ connect( option_flush, SIGNAL( stateChanged(int) ), SIGNAL( changed() ) );
+
+ if (!options.contains("utf8"))
+ option_utf8->hide();
+ else
+ option_utf8->setChecked(options["utf8"] == "true");
+ connect( option_utf8, SIGNAL( stateChanged(int) ), SIGNAL( changed() ) );
+
+ if (!options.contains("uid"))
+ option_uid->hide();
+ else
+ option_uid->setChecked(options["uid"] == "true");
+ connect( option_uid, SIGNAL( stateChanged(int) ), SIGNAL( changed() ) );
+
+ if (!options.contains("shortname"))
+ {
+ option_shortname->hide();
+ text_shortname->hide();
+ }
+ else
+ {
+ for (int index = 0; short_names[index]; ++index)
+ if (options["shortname"] == short_names[index])
+ {
+ option_shortname->setCurrentItem(index);
+ break;
+ }
+ connect( option_shortname, SIGNAL( activated(int) ), SIGNAL( changed() ) );
+ }
+
+ if (!options.contains("journaling"))
+ {
+ text_journaling->hide();
+ option_journaling->hide();
+ }
+ else
+ {
+ for (int index = 0; journales[index]; ++index)
+ if (options["journaling"] == journales[index])
+ {
+ option_journaling->setCurrentItem(index);
+ break;
+ }
+ connect( option_journaling, SIGNAL( activated(int) ), SIGNAL( changed() ) );
+ }
+
+ label_filesystem->setText(i18n("Filesystem: %1").arg(options["filesystem"]));
+ option_mountpoint->setText(options["mountpoint"]);
+ connect( option_mountpoint, SIGNAL( textChanged( const QString &) ), SIGNAL( changed() ) );
+ option_automount->setChecked(options["automount"] == "true");
+ connect( option_automount, SIGNAL( stateChanged(int) ), SIGNAL( changed() ) );
+
+ if (!options.contains("journaling") &&
+ !options.contains("shortname") &&
+ !options.contains("uid") &&
+ !options.contains("utf8") &&
+ !options.contains("flush"))
+ groupbox_specific->hide();
+
+ } else {
+
+ groupbox_generic->setEnabled(false);
+ groupbox_specific->setEnabled(false);
+ label_filesystem->hide();
+ }
+}
+
+PropertiesPage::~PropertiesPage()
+{
+}
+
+bool PropertiesPage::save()
+{
+ QStringList result;
+
+ if (options.contains("ro"))
+ result << QString("ro=%1").arg(option_ro->isChecked() ? "true" : "false");
+
+ if (options.contains("quiet"))
+ result << QString("quiet=%1").arg(option_quiet->isChecked() ? "true" : "false");
+
+ if (options.contains("sync"))
+ result << QString("sync=%1").arg(option_sync->isChecked() ? "true" : "false");
+
+ if (options.contains("atime"))
+ result << QString("atime=%1").arg(option_atime->isChecked() ? "true" : "false");
+
+ if (options.contains("flush"))
+ result << QString("flush=%1").arg(option_flush->isChecked() ? "true" : "false");
+
+ if (options.contains("utf8"))
+ result << QString("utf8=%1").arg(option_utf8->isChecked() ? "true" : "false");
+
+ if (options.contains("uid"))
+ result << QString("uid=%1").arg(option_uid->isChecked() ? "true" : "false");
+
+ if (options.contains("shortname"))
+ result << QString("shortname=%1").arg(short_names[option_shortname->currentItem()]);
+
+ if (options.contains("journaling"))
+ result << QString("journaling=%1").arg(journales[option_journaling->currentItem()]);
+
+ QString mp = option_mountpoint->text();
+ if (!mp.startsWith("/media/"))
+ {
+ KMessageBox::sorry(this, i18n("Mountpoint has to be below /media"));
+ return false;
+ }
+ result << QString("mountpoint=%1").arg(mp);
+ result << QString("automount=%1").arg(option_automount->isChecked() ? "true" : "false");
+
+ kdDebug() << result << endl;
+
+ DCOPRef mediamanager("kded", "mediamanager");
+ DCOPReply reply = mediamanager.call( "setMountoptions", id, result);
+
+ if (reply.isValid())
+ return (bool)reply;
+ else {
+ KMessageBox::sorry(this,
+ i18n("Saving the changes failed"));
+
+ return false;
+ }
+}
+
+#include "propertiespage.moc"
diff --git a/kioslave/media/propsdlgplugin/propertiespage.h b/kioslave/media/propsdlgplugin/propertiespage.h
new file mode 100644
index 000000000..7bc47599e
--- /dev/null
+++ b/kioslave/media/propsdlgplugin/propertiespage.h
@@ -0,0 +1,46 @@
+/*
+ Copyright (c) 2004 Jan Schaefer <j_schaef@informatik.uni-kl.de>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#ifndef PROPERTIESPAGE_H
+#define PROPERTIESPAGE_H
+
+#include "propertiespagegui.h"
+#include <qmap.h>
+
+class QCheckBox;
+class Medium;
+
+class PropertiesPage : public PropertiesPageGUI
+{
+ Q_OBJECT
+
+public:
+ PropertiesPage(QWidget* parent, const QString &_id);
+ virtual ~PropertiesPage();
+
+ bool save();
+
+protected:
+
+ QMap<QString,QString> options;
+ QString id;
+
+};
+
+#endif
diff --git a/kioslave/media/propsdlgplugin/propertiespagegui.ui b/kioslave/media/propsdlgplugin/propertiespagegui.ui
new file mode 100644
index 000000000..c4de4c059
--- /dev/null
+++ b/kioslave/media/propsdlgplugin/propertiespagegui.ui
@@ -0,0 +1,387 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>PropertiesPageGUI</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>PropertiesPageGUI</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>527</width>
+ <height>476</height>
+ </rect>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout17</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>groupbox_generic</cstring>
+ </property>
+ <property name="title">
+ <string>Generic Mount Options</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout15</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>option_ro</cstring>
+ </property>
+ <property name="text">
+ <string>Read only</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Mount the file system read-only.</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>option_quiet</cstring>
+ </property>
+ <property name="text">
+ <string>Quiet</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Attempts to chown or chmod files do not return errors, although they fail. Use with caution!</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>option_sync</cstring>
+ </property>
+ <property name="text">
+ <string>Synchronous</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>All I/O to the file system should be done synchronously.</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>option_atime</cstring>
+ </property>
+ <property name="text">
+ <string>Access time updates</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Update inode access time for each access.</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout14</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel3</cstring>
+ </property>
+ <property name="text">
+ <string>Mountpoint:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>option_mountpoint</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Under what directory this file system shall be mounted. Please note that there is no guarantee that the system will respect your wish. For one the directory has to be below /media - and it does not yet have to exist.</string>
+ </property>
+ </widget>
+ <widget class="QLineEdit">
+ <property name="name">
+ <cstring>option_mountpoint</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>option_automount</cstring>
+ </property>
+ <property name="text">
+ <string>Mount automatically</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Mount this file system automatically.</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>groupbox_specific</cstring>
+ </property>
+ <property name="title">
+ <string>Filesystem Specific Mount Options</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout11</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>option_flush</cstring>
+ </property>
+ <property name="text">
+ <string>Flushed IO</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Always flush all data to the hot plug devices immediately and don't cache it.</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>option_utf8</cstring>
+ </property>
+ <property name="text">
+ <string>UTF-8 charset</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>UTF8 is the filesystem safe 8-bit encoding of Unicode that is used by the console. It can be be enabled for the filesystem with this option.</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>option_uid</cstring>
+ </property>
+ <property name="text">
+ <string>Mount as user</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Mount this file system as user.</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout7</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>text_journaling</cstring>
+ </property>
+ <property name="text">
+ <string>Journaling:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>option_journaling</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;h2&gt;Specifies the journalling mode for file data. Metadata is always journaled. &lt;/h2&gt;
+
+&lt;h3&gt;&lt;b&gt;All Data&lt;/b&gt;&lt;/h3&gt;
+ All data is committed into the journal prior to being written into the main file system. This is the slowest variant with the highest data security.
+
+&lt;h3&gt;&lt;b&gt;Ordered&lt;/b&gt;&lt;/h3&gt;
+ All data is forced directly out to the main file system prior to its metadata being committed to the journal.
+
+&lt;h3&gt;&lt;b&gt;Write Back&lt;/b&gt;&lt;/h3&gt;
+ Data ordering is not preserved - data may be written into the main file system after its metadata has been committed to the journal. This is rumoured to be the highest-throughput option. It guarantees internal file system integrity, however it can allow old data to appear in files after a crash and journal recovery.</string>
+ </property>
+ </widget>
+ <widget class="QComboBox">
+ <item>
+ <property name="text">
+ <string>All Data</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Ordered</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Write Back</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>option_journaling</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;h2&gt;Specifies the journalling mode for file data. Metadata is always journaled. &lt;/h2&gt;
+
+&lt;h3&gt;&lt;b&gt;All Data&lt;/b&gt;&lt;/h3&gt;
+ All data is committed into the journal prior to being written into the main file system. This is the slowest variant with the highest data security.
+
+&lt;h3&gt;&lt;b&gt;Ordered&lt;/b&gt;&lt;/h3&gt;
+ All data is forced directly out to the main file system prior to its metadata being committed to the journal.
+
+&lt;h3&gt;&lt;b&gt;Write Back&lt;/b&gt;&lt;/h3&gt;
+ Data ordering is not preserved - data may be written into the main file system after its metadata has been committed to the journal. This is rumoured to be the highest-throughput option. It guarantees internal file system integrity, however it can allow old data to appear in files after a crash and journal recovery.</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout14</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>text_shortname</cstring>
+ </property>
+ <property name="text">
+ <string>Short names:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>option_shortname</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;h2&gt;Defines the behaviour for creation and display of filenames which fit into 8.3 characters. If a long name for a file exists, it will always be preferred display.&lt;/h2&gt;
+
+&lt;h3&gt;&lt;b&gt;Lower&lt;/b&gt;&lt;/h3&gt;
+Force the short name to lower case upon display; store a long name when the short name is not all upper case.
+
+&lt;h3&gt;&lt;b&gt;Windows 95&lt;/b&gt;&lt;/h3&gt;
+Force the short name to upper case upon display; store a long name when the short name is not all upper case.
+
+&lt;h3&gt;&lt;b&gt;Windows NT&lt;/b&gt;&lt;/h3&gt;
+Display the shortname as is; store a long name when the short name is not all lower case or all upper case.
+
+&lt;h3&gt;&lt;b&gt;Mixed&lt;/b&gt;&lt;/h3&gt;
+Display the short name as is; store a long name when the short name is not all upper case.</string>
+ </property>
+ </widget>
+ <widget class="QComboBox">
+ <item>
+ <property name="text">
+ <string>Lower</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Windows 95</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Windows NT</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Mixed</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>option_shortname</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;h2&gt;Defines the behaviour for creation and display of filenames which fit into 8.3 characters. If a long name for a file exists, it will always be preferred display.&lt;/h2&gt;
+
+&lt;h3&gt;&lt;b&gt;Lower&lt;/b&gt;&lt;/h3&gt;
+Force the short name to lower case upon display; store a long name when the short name is not all upper case.
+
+&lt;h3&gt;&lt;b&gt;Windows 95&lt;/b&gt;&lt;/h3&gt;
+Force the short name to upper case upon display; store a long name when the short name is not all upper case.
+
+&lt;h3&gt;&lt;b&gt;Windows NT&lt;/b&gt;&lt;/h3&gt;
+Display the shortname as is; store a long name when the short name is not all lower case or all upper case.
+
+&lt;h3&gt;&lt;b&gt;Mixed&lt;/b&gt;&lt;/h3&gt;
+Display the short name as is; store a long name when the short name is not all upper case.</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>label_filesystem</cstring>
+ </property>
+ <property name="text">
+ <string>Filesystem: iso9660</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ </hbox>
+</widget>
+<connections>
+ <connection>
+ <sender>option_ro</sender>
+ <signal>stateChanged(int)</signal>
+ <receiver>PropertiesPageGUI</receiver>
+ <slot>changedSlot()</slot>
+ </connection>
+</connections>
+<variables>
+ <variable>bool m_hasChanged;</variable>
+</variables>
+<signals>
+ <signal>changed()</signal>
+</signals>
+<slots>
+ <slot access="protected">changedSlot()</slot>
+</slots>
+<functions>
+ <function returnType="bool">hasChanged()</function>
+</functions>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/kioslave/media/propsdlgplugin/propertiespagegui.ui.h b/kioslave/media/propsdlgplugin/propertiespagegui.ui.h
new file mode 100644
index 000000000..45a9ca2d7
--- /dev/null
+++ b/kioslave/media/propsdlgplugin/propertiespagegui.ui.h
@@ -0,0 +1,22 @@
+/****************************************************************************
+** ui.h extension file, included from the uic-generated form implementation.
+**
+** If you wish to add, delete or rename functions or slots use
+** Qt Designer which will update this file, preserving your code. Create an
+** init() function in place of a constructor, and a destroy() function in
+** place of a destructor.
+*****************************************************************************/
+
+
+void PropertiesPageGUI::changedSlot()
+{
+ m_hasChanged = true;
+ emit changed();
+}
+
+bool PropertiesPageGUI::hasChanged()
+{
+ return m_hasChanged;
+}
+
+
diff --git a/kioslave/media/propsdlgplugin/propsdlgshareplugin.cpp b/kioslave/media/propsdlgplugin/propsdlgshareplugin.cpp
new file mode 100644
index 000000000..ebfd2c3de
--- /dev/null
+++ b/kioslave/media/propsdlgplugin/propsdlgshareplugin.cpp
@@ -0,0 +1,100 @@
+/*
+ Copyright (c) 2004 Jan Schaefer <j_schaef@informatik.uni-kl.de>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#include <qstring.h>
+#include <qvbox.h>
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qtimer.h>
+
+#include <kgenericfactory.h>
+#include <kdebug.h>
+#include <kpushbutton.h>
+#include <kfileshare.h>
+#include <kmessagebox.h>
+#include <kprocess.h>
+#include <kstandarddirs.h>
+#include <kdialog.h>
+#include <kglobal.h>
+#include <dcopref.h>
+
+#include "propertiespage.h"
+#include "propsdlgshareplugin.h"
+#include "../libmediacommon/medium.h"
+
+typedef KGenericFactory<PropsDlgSharePlugin, KPropertiesDialog> PropsDlgSharePluginFactory;
+
+K_EXPORT_COMPONENT_FACTORY( media_propsdlgplugin,
+ PropsDlgSharePluginFactory("media_propsdlgplugin") )
+
+class PropsDlgSharePlugin::Private
+{
+ public:
+ PropertiesPage* page;
+};
+
+PropsDlgSharePlugin::PropsDlgSharePlugin( KPropertiesDialog *dlg,
+ const char *, const QStringList & )
+ : KPropsDlgPlugin(dlg), d(0)
+{
+ if (properties->items().count() != 1)
+ return;
+
+ KFileItem *item = properties->items().first();
+
+ DCOPRef mediamanager("kded", "mediamanager");
+ kdDebug() << "properties " << item->url() << endl;
+ DCOPReply reply = mediamanager.call( "properties", item->url().url() );
+
+ if ( !reply.isValid() )
+ return;
+
+ QVBox* vbox = properties->addVBoxPage(i18n("&Mounting"));
+
+ d = new Private();
+
+ d->page = new PropertiesPage(vbox, Medium::create(reply).id());
+ connect(d->page, SIGNAL(changed()),
+ SLOT(slotChanged()));
+
+ // QTimer::singleShot(100, this, SLOT(slotChanged()));
+
+}
+
+void PropsDlgSharePlugin::slotChanged()
+{
+ kdDebug() << "slotChanged()\n";
+ setDirty(true);
+}
+
+PropsDlgSharePlugin::~PropsDlgSharePlugin()
+{
+ delete d;
+}
+
+void PropsDlgSharePlugin::applyChanges()
+{
+ kdDebug() << "applychanges\n";
+ if (!d->page->save()) {
+ properties->abortApplying();
+ }
+}
+
+
+#include "propsdlgshareplugin.moc"
+
diff --git a/kioslave/media/propsdlgplugin/propsdlgshareplugin.h b/kioslave/media/propsdlgplugin/propsdlgshareplugin.h
new file mode 100644
index 000000000..10ec47454
--- /dev/null
+++ b/kioslave/media/propsdlgplugin/propsdlgshareplugin.h
@@ -0,0 +1,44 @@
+/*
+ Copyright (c) 2004 Jan Schaefer <j_schaef@informatik.uni-kl.de>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#ifndef KONQFILESHAREPLUGIN_H
+#define KONQFILESHAREPLUGIN_H
+
+#include <kpropertiesdialog.h>
+
+class PropsDlgSharePlugin : public KPropsDlgPlugin
+{
+Q_OBJECT
+public:
+ PropsDlgSharePlugin( KPropertiesDialog *dlg, const char *, const QStringList & );
+ virtual ~PropsDlgSharePlugin();
+ virtual void applyChanges();
+
+public slots:
+ void slotChanged();
+
+private:
+ class Private;
+ Private *d;
+
+};
+
+#endif
+
+
diff --git a/kioslave/media/services/Makefile.am b/kioslave/media/services/Makefile.am
new file mode 100644
index 000000000..dded3c403
--- /dev/null
+++ b/kioslave/media/services/Makefile.am
@@ -0,0 +1,3 @@
+servicesdir = $(kde_datadir)/konqueror/servicemenus
+services_DATA = media_mount.desktop media_unmount.desktop media_eject.desktop media_safelyremove.desktop
+
diff --git a/kioslave/media/services/media_eject.desktop b/kioslave/media/services/media_eject.desktop
new file mode 100644
index 000000000..1ecd29fa8
--- /dev/null
+++ b/kioslave/media/services/media_eject.desktop
@@ -0,0 +1,90 @@
+[Desktop Entry]
+ServiceTypes=media/cdrom_mounted,media/cdrom_unmounted,media/cdwriter_mounted,media/cdwriter_unmounted,media/dvd_mounted,media/dvd_unmounted,media/audiocd,media/blankcd,media/blankdvd,media/dvdvideo,media/svcd,media/vcd
+Actions=MediaEject;
+X-KDE-Priority=TopLevel
+X-KDE-MediaNotifierHide=true
+
+[Desktop Action MediaEject]
+Name=Eject
+Name[af]=Uitskiet
+Name[ar]=أقذف
+Name[az]=Çıxart
+Name[be]=Вызваліць
+Name[bg]=Изваждане
+Name[bn]=ইজেক্ট
+Name[br]=Stlepel
+Name[bs]=Izbaci
+Name[ca]=Expulsa
+Name[cs]=Vysunout
+Name[csb]=Wësënie
+Name[cy]=Allfwrw
+Name[da]=Skub ud
+Name[de]=Auswerfen
+Name[el]=Εξαγωγή
+Name[eo]=Eligo
+Name[es]=Expulsar
+Name[et]=Väljastamine
+Name[eu]=Egotzi
+Name[fa]=پس زدن
+Name[fi]=Poista
+Name[fr]=Éjecter
+Name[fy]=Utsmytknop
+Name[ga]=Díchuir
+Name[gl]=Expulsar
+Name[he]=הוצא
+Name[hi]=बाहर
+Name[hr]=Izbaci
+Name[hu]=Kidobás
+Name[is]=Henda út
+Name[it]=Espelli
+Name[ja]=取り出し
+Name[ka]=CD-ს ამოღება
+Name[kk]=Алып-шығару
+Name[km]=ច្រាន​ចេញ
+Name[ko]=꺼내기
+Name[lo]=ເອົາແຜ່ນອອກ
+Name[lt]=Išmesti
+Name[lv]=Izņemt
+Name[mk]=Извади
+Name[mn]=Гаргах
+Name[ms]=Lenting
+Name[mt]=Iftaħ
+Name[nb]=Løs ut
+Name[nds]=Rutsmieten
+Name[ne]=निकाल्नुहोस्
+Name[nl]=Uitwerpen
+Name[nn]=Løys ut
+Name[nso]=Ntsha
+Name[oc]=Expulsa
+Name[pa]=ਬਾਹਰ ਕੱਢੋ
+Name[pl]=Wysuń
+Name[pt]=Ejectar
+Name[pt_BR]=Ejetar
+Name[ro]=Ejectează
+Name[ru]=Извлечь CD
+Name[rw]=Gusohora
+Name[se]=Bálkes olggos
+Name[sk]=Vysunúť
+Name[sl]=Izvrzi
+Name[sr]=Избаци
+Name[sr@Latn]=Izbaci
+Name[ss]=Khafuna
+Name[sv]=Mata ut
+Name[ta]=வெளித்தள்
+Name[te]=ఎజెక్ట్
+Name[tg]=Ихроҷ
+Name[th]=เอาแผ่นออก
+Name[tr]=Çıkart
+Name[tt]=Çığar
+Name[uk]=Виштовхнути
+Name[uz]=Chiqarish
+Name[uz@cyrillic]=Чиқариш
+Name[ven]=Bvisa
+Name[vi]=Đẩy đĩa ra
+Name[wa]=Fé rexhe
+Name[xh]=Khuphela ngaphandle
+Name[zh_CN]=弹出
+Name[zh_TW]=退出
+Name[zu]=Khipha
+Exec=kio_media_mounthelper -e %u
+
diff --git a/kioslave/media/services/media_mount.desktop b/kioslave/media/services/media_mount.desktop
new file mode 100644
index 000000000..1779d2208
--- /dev/null
+++ b/kioslave/media/services/media_mount.desktop
@@ -0,0 +1,87 @@
+[Desktop Entry]
+ServiceTypes=media/cdrom_unmounted,media/cdwriter_unmounted,media/dvd_unmounted,media/floppy5_unmounted,media/floppy_unmounted,media/hdd_unmounted,media/nfs_unmounted,media/removable_unmounted,media/smb_unmounted,media/zip_unmounted,media/camera_unmounted
+Actions=MediaMount;
+X-KDE-Priority=TopLevel
+X-KDE-MediaNotifierHide=true
+
+[Desktop Action MediaMount]
+Name=Mount
+Name[af]=Koppel
+Name[ar]=ركِب
+Name[az]=Bağla
+Name[be]=Прымацаваць
+Name[bg]=Монтиране
+Name[bn]=মাউন্ট
+Name[br]=Marc'hañ
+Name[bs]=Montiraj
+Name[ca]=Munta
+Name[cs]=Připojit
+Name[csb]=Mòntujë
+Name[cy]=Gosod
+Name[da]=Montér
+Name[de]=Laufwerk einbinden
+Name[el]=Προσάρτηση
+Name[eo]=Surmeti
+Name[es]=Montar
+Name[et]=Ühenda
+Name[eu]=Muntatu
+Name[fa]=سوار کردن
+Name[fi]=Liitä
+Name[fr]=Monter
+Name[fy]=Oankeppelje (mount)
+Name[ga]=Feistigh
+Name[gl]=Montar
+Name[he]=חבר
+Name[hi]=माउन्ट
+Name[hr]=Pristupi
+Name[hsb]=montować
+Name[hu]=Csatlakoztatás
+Name[is]=Tengja
+Name[it]=Monta
+Name[ja]=マウント
+Name[ka]=მონტირება
+Name[kk]=Тіркеу
+Name[km]=រៀបចំ
+Name[lo]=ຈໍພາບ
+Name[lt]=Montuoti
+Name[lv]=Piemontēt
+Name[mk]=Монтирај
+Name[mn]=Залгах
+Name[ms]=Lekap
+Name[mt]=Immonta
+Name[nb]=Monter
+Name[nds]=Inhangen
+Name[ne]=माउन्ट
+Name[nl]=Aankoppelen (mount)
+Name[nn]=Monter
+Name[nso]=Nameletsa
+Name[pa]=ਮਾਊਟ
+Name[pl]=Zamontuj
+Name[pt]=Montar
+Name[pt_BR]=Montar
+Name[ro]=Montează
+Name[ru]=Подключить
+Name[rw]=Gushyiramo
+Name[se]=Čana
+Name[sk]=Pripojiť
+Name[sl]=Priklopi
+Name[sr]=Монтирај
+Name[sr@Latn]=Montiraj
+Name[sv]=Montera
+Name[ta]=ஏற்று
+Name[tg]=Васл кунӣ
+Name[th]=เม้านท์
+Name[tr]=Bağla
+Name[tt]=Bäyläp quy
+Name[uk]=Змонтувати
+Name[uz]=Ulash
+Name[uz@cyrillic]=Улаш
+Name[ven]=Gonya
+Name[vi]=Kết nối
+Name[wa]=Monter
+Name[xh]=Layisha
+Name[zh_CN]=挂载
+Name[zh_TW]=掛載
+Name[zu]=Yenyusa
+Exec=kio_media_mounthelper -m %u
+
diff --git a/kioslave/media/services/media_safelyremove.desktop b/kioslave/media/services/media_safelyremove.desktop
new file mode 100644
index 000000000..298a5f2e5
--- /dev/null
+++ b/kioslave/media/services/media_safelyremove.desktop
@@ -0,0 +1,75 @@
+[Desktop Entry]
+ServiceTypes=media/removable_mounted,media/removable_unmounted,media/camera_mounted,media/camera_unmounted
+Actions=MediaSafelyRemove;
+X-KDE-Priority=TopLevel
+X-KDE-MediaNotifierHide=true
+
+[Desktop Action MediaSafelyRemove]
+Name=Safely Remove
+Name[af]=Verwyder veilig
+Name[ar]=أحذف بأمان
+Name[be]=Бяспечна адлучыць
+Name[bg]=Безопасно изваждане
+Name[bn]=নিরাপদভাবে সরাও
+Name[bs]=Sigurno ukloni
+Name[ca]=Extreu amb seguretat
+Name[cs]=Bezpečně odstranit
+Name[csb]=Remôj na bezpieczny ôrt
+Name[da]=Fjern sikkert
+Name[de]=Sicher entfernen
+Name[el]=Ασφαλής αφαίρεση
+Name[eo]=Sekura Forigo
+Name[es]=Extracción segura
+Name[et]=Eemalda turvaliselt
+Name[eu]=Atera arriskurik gabe
+Name[fa]=حذف امن
+Name[fi]=Poista turvallisesti
+Name[fr]=Enlever en toute sécurité
+Name[fy]=Feilich ferwiderje
+Name[ga]=Bain Amach go Sábháilte
+Name[gl]=Eliminar de Maneira Segura
+Name[he]=שליפה בבטחה
+Name[hr]=Slobodno uklonite
+Name[hu]=Biztonságos leválasztás
+Name[is]=Fjarlægja öruggt
+Name[it]=Rimozione sicura
+Name[ja]=安全に取り除く
+Name[ka]=უსაფრთხოდ გამორთვა
+Name[kk]=Қауіпсіз алып шығу
+Name[km]=យកចេញ​ដោយ​សុវត្ថិភាព
+Name[lt]=Saugiai pašalinti
+Name[mk]=Безбедно отстрани
+Name[ms]=Buang Dengan Selamat
+Name[nb]=Sikker fjerning
+Name[nds]=Seker rutnehmen
+Name[ne]=सुरक्षीत रुपमा हटाउनुहोस्
+Name[nl]=Veilig verwijderen
+Name[nn]=Trygg fjerning
+Name[pa]=ਸੁਰੱਖਿਅਤ ਹਟਾਓ
+Name[pl]=Usuń w sposób bezpieczny
+Name[pt]=Retirar com Segurança
+Name[pt_BR]=Remover de Modo Seguro
+Name[ro]=Scoate în siguranță
+Name[ru]=Безопасно извлечь
+Name[rw]=Gukuramo Neza
+Name[se]=Dorvvošlaš eretváldin
+Name[sk]=Bezpečne odpojiť
+Name[sl]=Varno odstrani
+Name[sr]=Безбедно уклони
+Name[sr@Latn]=Bezbedno ukloni
+Name[sv]=Säker urkoppling
+Name[ta]=பாதுகாப்பாக நீக்கு
+Name[te]=జాగరత్తగా తియి
+Name[tg]=Баровардани бехетар
+Name[th]=ถอดออกอย่างปลอดภัย
+Name[tr]=Güvenli Kaldır
+Name[tt]=İmin Çığaru
+Name[uk]=Безпечно вилучити
+Name[uz]=Ehtiyotlik bilan uzish
+Name[uz@cyrillic]=Эҳтиётлик билан узиш
+Name[vi]=Gỡ ra An toàn
+Name[wa]=Ositer e såvrité
+Name[zh_CN]=安全删除
+Name[zh_TW]=安全的移除
+Exec=kio_media_mounthelper -s %u
+
diff --git a/kioslave/media/services/media_unmount.desktop b/kioslave/media/services/media_unmount.desktop
new file mode 100644
index 000000000..537750095
--- /dev/null
+++ b/kioslave/media/services/media_unmount.desktop
@@ -0,0 +1,87 @@
+[Desktop Entry]
+ServiceTypes=media/cdrom_mounted,media/cdwriter_mounted,media/dvd_mounted,media/floppy5_mounted,media/floppy_mounted,media/hdd_mounted,media/nfs_mounted,media/smb_mounted,media/zip_mounted,media/vcd,media/svcd,media/dvdvideo
+Actions=MediaUnmount;
+X-KDE-Priority=TopLevel
+X-KDE-MediaNotifierHide=true
+
+[Desktop Action MediaUnmount]
+Name=Unmount
+Name[af]=Ontkoppel
+Name[ar]=أزل التركيب
+Name[az]=Ayır
+Name[be]=Адмацаваць
+Name[bg]=Демонтиране
+Name[bn]=আনমাউন্ট
+Name[br]=Divarc'hañ
+Name[bs]=Demontiraj
+Name[ca]= Desmunta
+Name[cs]=Odpojit
+Name[csb]=Òdmòntujë
+Name[cy]=Dadosod
+Name[da]=Afmontér
+Name[de]=Laufwerkeinbindung lösen
+Name[el]=Αποπροσάρτηση
+Name[eo]=Demeti
+Name[es]=Desmontar
+Name[et]=Lahuta
+Name[eu]=Desmuntatu
+Name[fa]=پیاده کردن
+Name[fi]=Irrota
+Name[fr]=Libérer
+Name[fy]=Ofkeppelje (unmount)
+Name[ga]=Dífheistigh
+Name[gl]=Desmontar
+Name[he]=נתק
+Name[hi]=अनमाउन्ट
+Name[hr]=Napusti
+Name[hsb]=Wotmontować
+Name[hu]=Leválasztás
+Name[is]=Aftengja
+Name[it]=Smonta
+Name[ja]=マウント解除
+Name[ka]=დემონტირება
+Name[kk]=Тіркеуден шығару
+Name[km]=មិន​រៀបចំ
+Name[lo]=ຫັງກາລີ
+Name[lt]=Išmontuoti
+Name[lv]=Nomontēt
+Name[mk]=Одмонтирај
+Name[mn]=Салгах
+Name[ms]=Nyahlekap
+Name[mt]=Żmonta
+Name[nb]=Avmonter
+Name[nds]=Afhangen
+Name[ne]=अनमाउन्ट
+Name[nl]=Afkoppelen (unmount)
+Name[nn]=Avmonter
+Name[nso]=Theosa
+Name[pa]=ਅਨਮਾਉਟ
+Name[pl]=Odmontuj
+Name[pt]=Desmontar
+Name[pt_BR]=Desmontar
+Name[ro]=Demontează
+Name[ru]=Отключить
+Name[rw]=Gukuramo
+Name[se]=Gálgga
+Name[sk]=Odpojiť
+Name[sl]=Odklopi
+Name[sr]=Демонтирај
+Name[sr@Latn]=Demontiraj
+Name[sv]=Avmontera
+Name[ta]=வெளியேற்று
+Name[tg]=Ҷудо кунӣ
+Name[th]=เลิกเม้านท์
+Name[tr]=Ayır
+Name[tt]=Bäyläwne çiş
+Name[uk]=Демонтувати
+Name[uz]=Uzish
+Name[uz@cyrillic]=Узиш
+Name[ven]=Usa gonya
+Name[vi]=Gỡ ra
+Name[wa]=Dismonter
+Name[xh]=Sukuyilayisha
+Name[zh_CN]=卸载
+Name[zh_TW]=卸載
+Name[zu]=Yehlisa
+Exec=kio_media_mounthelper -u %u
+
diff --git a/kioslave/media/testmedia.cpp b/kioslave/media/testmedia.cpp
new file mode 100644
index 000000000..d3f19512c
--- /dev/null
+++ b/kioslave/media/testmedia.cpp
@@ -0,0 +1,69 @@
+/* This file is part of the KDE project
+ Copyright (c) 2004 Kévin Ottens <ervin ipsquad net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "kio_media.h"
+#include "testmedia.h"
+
+#include <config.h>
+
+#include <kapplication.h>
+#include <kdebug.h>
+#include <kcmdlineargs.h>
+
+#include <stdlib.h>
+
+static bool check(const QString& txt, QString a, QString b)
+{
+ if (a.isEmpty())
+ a = QString::null;
+ if (b.isEmpty())
+ b = QString::null;
+ if (a == b) {
+ kdDebug() << txt << " : checking '" << a << "' against expected value '" << b << "'... " << "ok" << endl;
+ }
+ else {
+ kdDebug() << txt << " : checking '" << a << "' against expected value '" << b << "'... " << "KO !" << endl;
+ exit(1);
+ }
+ return true;
+}
+
+int main(int argc, char *argv[])
+{
+ KApplication::disableAutoDcopRegistration();
+ KCmdLineArgs::init(argc,argv,"testmedia", 0, 0, 0, 0);
+ KApplication app;
+
+ TestMedia test;
+ test.setup();
+ test.runAll();
+ kdDebug() << "All tests OK." << endl;
+ return 0; // success. The exit(1) in check() is what happens in case of failure.
+}
+
+void TestMedia::setup()
+{
+
+}
+
+void TestMedia::runAll()
+{
+
+}
+
diff --git a/kioslave/media/testmedia.h b/kioslave/media/testmedia.h
new file mode 100644
index 000000000..dd2481bda
--- /dev/null
+++ b/kioslave/media/testmedia.h
@@ -0,0 +1,34 @@
+/* This file is part of the KDE project
+ Copyright (c) 2004 Kvin Ottens <ervin ipsquad net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef TESTMEDIA_H
+#define TESTMEDIA_H
+
+class TestMedia
+{
+public:
+ TestMedia() {}
+ void setup();
+ void runAll();
+
+ // tests
+
+};
+
+#endif