summaryrefslogtreecommitdiffstats
path: root/kpilot/conduits
diff options
context:
space:
mode:
Diffstat (limited to 'kpilot/conduits')
-rw-r--r--kpilot/conduits/CMakeLists.txt35
-rw-r--r--kpilot/conduits/Makefile.am30
-rw-r--r--kpilot/conduits/abbrowserconduit/CMakeLists.txt46
-rw-r--r--kpilot/conduits/abbrowserconduit/KPilotCustomFieldEditor.ui276
-rw-r--r--kpilot/conduits/abbrowserconduit/Makefile.am24
-rw-r--r--kpilot/conduits/abbrowserconduit/abbrowser-conduit.cc1897
-rw-r--r--kpilot/conduits/abbrowserconduit/abbrowser-conduit.h222
-rw-r--r--kpilot/conduits/abbrowserconduit/abbrowser-factory.cc45
-rw-r--r--kpilot/conduits/abbrowserconduit/abbrowser-factory.h40
-rw-r--r--kpilot/conduits/abbrowserconduit/abbrowser-setup.cc195
-rw-r--r--kpilot/conduits/abbrowserconduit/abbrowser-setup.h52
-rw-r--r--kpilot/conduits/abbrowserconduit/abbrowserSettings.kcfgc7
-rw-r--r--kpilot/conduits/abbrowserconduit/abbrowser_conduit.desktop116
-rw-r--r--kpilot/conduits/abbrowserconduit/abbrowserconduit.kcfg80
-rw-r--r--kpilot/conduits/abbrowserconduit/kabcRecord.cc710
-rw-r--r--kpilot/conduits/abbrowserconduit/kabcRecord.h263
-rw-r--r--kpilot/conduits/abbrowserconduit/kaddressbookConduit.ui746
-rw-r--r--kpilot/conduits/abbrowserconduit/resolutionDialog.cc323
-rw-r--r--kpilot/conduits/abbrowserconduit/resolutionDialog.h70
-rw-r--r--kpilot/conduits/abbrowserconduit/resolutionDialog_base.ui129
-rw-r--r--kpilot/conduits/abbrowserconduit/resolutionTable.h70
-rw-r--r--kpilot/conduits/configure.in.bot14
-rw-r--r--kpilot/conduits/configure.in.in241
-rw-r--r--kpilot/conduits/docconduit/CMakeLists.txt87
-rw-r--r--kpilot/conduits/docconduit/DOC-converter.cc631
-rw-r--r--kpilot/conduits/docconduit/DOC-converter.h183
-rw-r--r--kpilot/conduits/docconduit/Icons/CMakeLists.txt3
-rw-r--r--kpilot/conduits/docconduit/Icons/Makefile.am7
-rw-r--r--kpilot/conduits/docconduit/Icons/cr16-app-kpalmdoc.pngbin0 -> 747 bytes
-rw-r--r--kpilot/conduits/docconduit/Icons/cr22-app-kpalmdoc.pngbin0 -> 1088 bytes
-rw-r--r--kpilot/conduits/docconduit/Icons/cr32-app-kpalmdoc.pngbin0 -> 2007 bytes
-rw-r--r--kpilot/conduits/docconduit/Icons/cr48-app-kpalmdoc.pngbin0 -> 3254 bytes
-rw-r--r--kpilot/conduits/docconduit/Makefile.am38
-rw-r--r--kpilot/conduits/docconduit/bmkSpecification.txt199
-rw-r--r--kpilot/conduits/docconduit/doc-conduit.cc1018
-rw-r--r--kpilot/conduits/docconduit/doc-conduit.h152
-rw-r--r--kpilot/conduits/docconduit/doc-conflictdialog.cc182
-rw-r--r--kpilot/conduits/docconduit/doc-conflictdialog.h83
-rw-r--r--kpilot/conduits/docconduit/doc-factory.cc116
-rw-r--r--kpilot/conduits/docconduit/doc-factory.h74
-rw-r--r--kpilot/conduits/docconduit/doc-setup.cc136
-rw-r--r--kpilot/conduits/docconduit/doc-setup.h47
-rw-r--r--kpilot/conduits/docconduit/doc-setupdialog.ui557
-rw-r--r--kpilot/conduits/docconduit/doc_conduit.desktop59
-rw-r--r--kpilot/conduits/docconduit/docconduit.kcfg54
-rw-r--r--kpilot/conduits/docconduit/docconduitSettings.kcfgc7
-rw-r--r--kpilot/conduits/docconduit/kpalmdoc.cpp58
-rw-r--r--kpilot/conduits/docconduit/kpalmdoc.desktop65
-rw-r--r--kpilot/conduits/docconduit/kpalmdoc.kcfg41
-rw-r--r--kpilot/conduits/docconduit/kpalmdoc.upd6
-rw-r--r--kpilot/conduits/docconduit/kpalmdocSettings.kcfgc7
-rw-r--r--kpilot/conduits/docconduit/kpalmdoc_dlg.cc529
-rw-r--r--kpilot/conduits/docconduit/kpalmdoc_dlg.h67
-rw-r--r--kpilot/conduits/docconduit/kpalmdoc_dlgbase.ui435
-rw-r--r--kpilot/conduits/docconduit/makedoc9.cc405
-rw-r--r--kpilot/conduits/docconduit/makedoc9.h111
-rw-r--r--kpilot/conduits/docconduit/pilotDOCBookmark.cc87
-rw-r--r--kpilot/conduits/docconduit/pilotDOCBookmark.h51
-rw-r--r--kpilot/conduits/docconduit/pilotDOCEntry.cc92
-rw-r--r--kpilot/conduits/docconduit/pilotDOCEntry.h73
-rw-r--r--kpilot/conduits/docconduit/pilotDOCHead.cc101
-rw-r--r--kpilot/conduits/docconduit/pilotDOCHead.h62
-rw-r--r--kpilot/conduits/docconduit/tests/testcompress.cpp59
-rw-r--r--kpilot/conduits/knotes/CMakeLists.txt52
-rw-r--r--kpilot/conduits/knotes/Makefile.am21
-rw-r--r--kpilot/conduits/knotes/cr32-app-knotesconduit.pngbin0 -> 369 bytes
-rw-r--r--kpilot/conduits/knotes/knotes-action.cc872
-rw-r--r--kpilot/conduits/knotes/knotes-action.h113
-rw-r--r--kpilot/conduits/knotes/knotes-conduit.desktop94
-rw-r--r--kpilot/conduits/knotes/knotes-factory.cc133
-rw-r--r--kpilot/conduits/knotes/knotes-factory.h70
-rw-r--r--kpilot/conduits/knotes/knotes-setup.cc83
-rw-r--r--kpilot/conduits/knotes/knotes-setup.h49
-rw-r--r--kpilot/conduits/knotes/knotesconduit.kcfg25
-rw-r--r--kpilot/conduits/knotes/knotesconduitSettings.kcfgc7
-rw-r--r--kpilot/conduits/knotes/setup_base.ui88
-rw-r--r--kpilot/conduits/malconduit/CMakeLists.txt48
-rw-r--r--kpilot/conduits/malconduit/Makefile.am18
-rw-r--r--kpilot/conduits/malconduit/README12
-rw-r--r--kpilot/conduits/malconduit/mal-conduit.cc319
-rw-r--r--kpilot/conduits/malconduit/mal-conduit.h66
-rw-r--r--kpilot/conduits/malconduit/mal-factory.cc143
-rw-r--r--kpilot/conduits/malconduit/mal-factory.h67
-rw-r--r--kpilot/conduits/malconduit/mal-setup.cc185
-rw-r--r--kpilot/conduits/malconduit/mal-setup.h54
-rw-r--r--kpilot/conduits/malconduit/mal-setup_dialog.ui634
-rw-r--r--kpilot/conduits/malconduit/mal_conduit.desktop96
-rw-r--r--kpilot/conduits/malconduit/malconduit.kcfg56
-rw-r--r--kpilot/conduits/malconduit/malconduitSettings.kcfgc7
-rw-r--r--kpilot/conduits/memofileconduit/CMakeLists.txt44
-rw-r--r--kpilot/conduits/memofileconduit/Makefile.am16
-rw-r--r--kpilot/conduits/memofileconduit/design/SQD - copyHHToPC.jpgbin0 -> 111060 bytes
-rw-r--r--kpilot/conduits/memofileconduit/design/SQD - copyPCToHH.jpgbin0 -> 69573 bytes
-rw-r--r--kpilot/conduits/memofileconduit/design/SQD - detailed load.jpgbin0 -> 119635 bytes
-rw-r--r--kpilot/conduits/memofileconduit/design/SQD - sync.jpgbin0 -> 112438 bytes
-rw-r--r--kpilot/conduits/memofileconduit/memofile-conduit.cc567
-rw-r--r--kpilot/conduits/memofileconduit/memofile-conduit.desktop93
-rw-r--r--kpilot/conduits/memofileconduit/memofile-conduit.h92
-rw-r--r--kpilot/conduits/memofileconduit/memofile-factory.cc128
-rw-r--r--kpilot/conduits/memofileconduit/memofile-factory.h40
-rw-r--r--kpilot/conduits/memofileconduit/memofile.cc239
-rw-r--r--kpilot/conduits/memofileconduit/memofile.h113
-rw-r--r--kpilot/conduits/memofileconduit/memofileSettings.kcfgc7
-rw-r--r--kpilot/conduits/memofileconduit/memofileconduit.kcfg16
-rw-r--r--kpilot/conduits/memofileconduit/memofileconduit.xmi241
-rw-r--r--kpilot/conduits/memofileconduit/memofiles.cc700
-rw-r--r--kpilot/conduits/memofileconduit/memofiles.h96
-rw-r--r--kpilot/conduits/memofileconduit/setup_base.ui143
-rw-r--r--kpilot/conduits/notepadconduit/CMakeLists.txt38
-rw-r--r--kpilot/conduits/notepadconduit/Makefile.am14
-rw-r--r--kpilot/conduits/notepadconduit/notepad-conduit.cc265
-rw-r--r--kpilot/conduits/notepadconduit/notepad-conduit.desktop65
-rw-r--r--kpilot/conduits/notepadconduit/notepad-conduit.h94
-rw-r--r--kpilot/conduits/notepadconduit/notepad-factory.cc124
-rw-r--r--kpilot/conduits/notepadconduit/notepad-factory.h38
-rw-r--r--kpilot/conduits/notepadconduit/notepad-setup.ui79
-rw-r--r--kpilot/conduits/notepadconduit/notepadconduit.kcfg14
-rw-r--r--kpilot/conduits/notepadconduit/notepadconduit.kcfgc7
-rw-r--r--kpilot/conduits/null/CMakeLists.txt38
-rw-r--r--kpilot/conduits/null/Makefile.am15
-rw-r--r--kpilot/conduits/null/null-conduit.cc98
-rw-r--r--kpilot/conduits/null/null-conduit.desktop64
-rw-r--r--kpilot/conduits/null/null-conduit.h65
-rw-r--r--kpilot/conduits/null/null-factory.cc125
-rw-r--r--kpilot/conduits/null/null-factory.h40
-rw-r--r--kpilot/conduits/null/nullSettings.kcfgc7
-rw-r--r--kpilot/conduits/null/nullconduit.kcfg13
-rw-r--r--kpilot/conduits/null/setup_base.ui128
-rw-r--r--kpilot/conduits/popmail/CMakeLists.txt43
-rw-r--r--kpilot/conduits/popmail/Makefile.am24
-rw-r--r--kpilot/conduits/popmail/popmail-conduit.cc416
-rw-r--r--kpilot/conduits/popmail/popmail-conduit.desktop109
-rw-r--r--kpilot/conduits/popmail/popmail-conduit.h74
-rw-r--r--kpilot/conduits/popmail/popmail-factory.cc47
-rw-r--r--kpilot/conduits/popmail/popmail-factory.h37
-rw-r--r--kpilot/conduits/popmail/popmail.kcfg25
-rw-r--r--kpilot/conduits/popmail/popmailSettings.kcfgc7
-rw-r--r--kpilot/conduits/popmail/setup-dialog.ui141
-rw-r--r--kpilot/conduits/popmail/setupDialog.cc158
-rw-r--r--kpilot/conduits/popmail/setupDialog.h62
-rw-r--r--kpilot/conduits/recordconduit/Makefile.am15
-rw-r--r--kpilot/conduits/recordconduit/factory.cc144
-rw-r--r--kpilot/conduits/recordconduit/factory.h40
-rw-r--r--kpilot/conduits/recordconduit/record-conduit.desktop93
-rw-r--r--kpilot/conduits/recordconduit/settings.kcfg22
-rw-r--r--kpilot/conduits/recordconduit/settings.kcfgc7
-rw-r--r--kpilot/conduits/recordconduit/setup_base.ui158
-rw-r--r--kpilot/conduits/sysinfoconduit/CMakeLists.txt50
-rw-r--r--kpilot/conduits/sysinfoconduit/Makefile.am24
-rw-r--r--kpilot/conduits/sysinfoconduit/Template.html184
-rw-r--r--kpilot/conduits/sysinfoconduit/Template.txt76
-rw-r--r--kpilot/conduits/sysinfoconduit/sysinfo-conduit.cc611
-rw-r--r--kpilot/conduits/sysinfoconduit/sysinfo-conduit.h79
-rw-r--r--kpilot/conduits/sysinfoconduit/sysinfo-factory.cc43
-rw-r--r--kpilot/conduits/sysinfoconduit/sysinfo-factory.h36
-rw-r--r--kpilot/conduits/sysinfoconduit/sysinfo-setup.cc198
-rw-r--r--kpilot/conduits/sysinfoconduit/sysinfo-setup.h47
-rw-r--r--kpilot/conduits/sysinfoconduit/sysinfo-setup_dialog.ui214
-rw-r--r--kpilot/conduits/sysinfoconduit/sysinfoSettings.kcfgc7
-rw-r--r--kpilot/conduits/sysinfoconduit/sysinfo_conduit.desktop111
-rw-r--r--kpilot/conduits/sysinfoconduit/sysinfoconduit.kcfg64
-rw-r--r--kpilot/conduits/timeconduit/CMakeLists.txt44
-rw-r--r--kpilot/conduits/timeconduit/Makefile.am22
-rw-r--r--kpilot/conduits/timeconduit/time-conduit.cc121
-rw-r--r--kpilot/conduits/timeconduit/time-conduit.h49
-rw-r--r--kpilot/conduits/timeconduit/time-factory.cc46
-rw-r--r--kpilot/conduits/timeconduit/time-factory.h41
-rw-r--r--kpilot/conduits/timeconduit/time-setup.cc86
-rw-r--r--kpilot/conduits/timeconduit/time-setup.h50
-rw-r--r--kpilot/conduits/timeconduit/time-setup_dialog.ui122
-rw-r--r--kpilot/conduits/timeconduit/timeConduitSettings.kcfgc7
-rw-r--r--kpilot/conduits/timeconduit/time_conduit.desktop107
-rw-r--r--kpilot/conduits/timeconduit/timeconduit.kcfg17
-rw-r--r--kpilot/conduits/vcalconduit/CMakeLists.txt75
-rw-r--r--kpilot/conduits/vcalconduit/Makefile.am43
-rw-r--r--kpilot/conduits/vcalconduit/README11
-rw-r--r--kpilot/conduits/vcalconduit/cleanupstate.cc132
-rw-r--r--kpilot/conduits/vcalconduit/cleanupstate.h49
-rw-r--r--kpilot/conduits/vcalconduit/conduitstate.h86
-rw-r--r--kpilot/conduits/vcalconduit/deleteunsyncedhhstate.cc115
-rw-r--r--kpilot/conduits/vcalconduit/deleteunsyncedhhstate.h53
-rw-r--r--kpilot/conduits/vcalconduit/deleteunsyncedpcstate.cc135
-rw-r--r--kpilot/conduits/vcalconduit/deleteunsyncedpcstate.h53
-rw-r--r--kpilot/conduits/vcalconduit/hhtopcstate.cc249
-rw-r--r--kpilot/conduits/vcalconduit/hhtopcstate.h55
-rw-r--r--kpilot/conduits/vcalconduit/initstate.cc109
-rw-r--r--kpilot/conduits/vcalconduit/initstate.h52
-rw-r--r--kpilot/conduits/vcalconduit/kcalRecord.cc143
-rw-r--r--kpilot/conduits/vcalconduit/kcalRecord.h49
-rw-r--r--kpilot/conduits/vcalconduit/korganizerConduit.ui275
-rw-r--r--kpilot/conduits/vcalconduit/pctohhstate.cc159
-rw-r--r--kpilot/conduits/vcalconduit/pctohhstate.h54
-rw-r--r--kpilot/conduits/vcalconduit/teststate.cc127
-rw-r--r--kpilot/conduits/vcalconduit/teststate.h55
-rw-r--r--kpilot/conduits/vcalconduit/todo-conduit.cc373
-rw-r--r--kpilot/conduits/vcalconduit/todo-conduit.desktop107
-rw-r--r--kpilot/conduits/vcalconduit/todo-conduit.h108
-rw-r--r--kpilot/conduits/vcalconduit/todo-factory.cc46
-rw-r--r--kpilot/conduits/vcalconduit/todo-factory.h40
-rw-r--r--kpilot/conduits/vcalconduit/todo-setup.cc86
-rw-r--r--kpilot/conduits/vcalconduit/todo-setup.h44
-rw-r--r--kpilot/conduits/vcalconduit/todoRecord.cc141
-rw-r--r--kpilot/conduits/vcalconduit/todoRecord.h49
-rw-r--r--kpilot/conduits/vcalconduit/vcal-conduit.cc309
-rw-r--r--kpilot/conduits/vcalconduit/vcal-conduit.desktop105
-rw-r--r--kpilot/conduits/vcalconduit/vcal-conduit.h101
-rw-r--r--kpilot/conduits/vcalconduit/vcal-conduitbase.cc622
-rw-r--r--kpilot/conduits/vcalconduit/vcal-conduitbase.h202
-rw-r--r--kpilot/conduits/vcalconduit/vcal-factory.cc50
-rw-r--r--kpilot/conduits/vcalconduit/vcal-factory.h41
-rw-r--r--kpilot/conduits/vcalconduit/vcal-factorybase.h44
-rw-r--r--kpilot/conduits/vcalconduit/vcal-setup.cc78
-rw-r--r--kpilot/conduits/vcalconduit/vcal-setup.h46
-rw-r--r--kpilot/conduits/vcalconduit/vcal-setupbase.cc110
-rw-r--r--kpilot/conduits/vcalconduit/vcal-setupbase.h51
-rw-r--r--kpilot/conduits/vcalconduit/vcalRecord.cc548
-rw-r--r--kpilot/conduits/vcalconduit/vcalRecord.h51
-rw-r--r--kpilot/conduits/vcalconduit/vcalconduitSettings.kcfgc7
-rw-r--r--kpilot/conduits/vcalconduit/vcalconduitbase.kcfg31
219 files changed, 28238 insertions, 0 deletions
diff --git a/kpilot/conduits/CMakeLists.txt b/kpilot/conduits/CMakeLists.txt
new file mode 100644
index 000000000..e8f49e53f
--- /dev/null
+++ b/kpilot/conduits/CMakeLists.txt
@@ -0,0 +1,35 @@
+include_directories(
+ ${CMAKE_BINARY_DIR}/lib
+ ${CMAKE_SOURCE_DIR}/lib
+ ${CMAKE_CURRENT_BINARY_DIR}
+)
+
+add_subdirectory(abbrowserconduit)
+add_subdirectory(docconduit)
+add_subdirectory(knotes)
+add_subdirectory(memofileconduit)
+add_subdirectory(notepadconduit)
+add_subdirectory(null)
+add_subdirectory(popmail)
+add_subdirectory(sysinfoconduit)
+add_subdirectory(timeconduit)
+
+FIND_PATH( HAVE_CALENDARLOCAL_H "libkcal/calendarlocal.h" ${KDE3_INCLUDE_DIR} )
+
+IF (HAVE_CALENDARLOCAL_H)
+ add_subdirectory(vcalconduit)
+ELSE (HAVE_CALENDARLOCAL_H)
+ MESSAGE(STATUS "No KDE PIM development headers were found.")
+ENDIF (HAVE_CALENDARLOCAL_H)
+
+###
+#
+# MAL seems to be broken, or the MAL API has changed somewhat
+# since the last time that the conduit was compiled by the development
+# team. Since we don't use the conduit it is disabled.
+IF (MAL_FOUND)
+ add_subdirectory(malconduit)
+ELSE (MAL_FOUND)
+ MESSAGE(STATUS "Couldn't find mal. Won't be able to build malconduit")
+ENDIF (MAL_FOUND)
+
diff --git a/kpilot/conduits/Makefile.am b/kpilot/conduits/Makefile.am
new file mode 100644
index 000000000..fed44984b
--- /dev/null
+++ b/kpilot/conduits/Makefile.am
@@ -0,0 +1,30 @@
+###
+### The NULL conduit is a neat programming example, but shouldn't be
+### installed on user systems.
+###
+
+if include_malconduit
+MAL_SUBDIR = malconduit
+else
+MAL_SUBDIR =
+endif
+
+SUBDIRS = \
+ abbrowserconduit \
+ docconduit \
+ knotes \
+ $(MAL_SUBDIR) \
+ memofileconduit \
+ notepadconduit \
+ popmail \
+ sysinfoconduit \
+ timeconduit \
+ vcalconduit
+
+###
+### Subdirs you might have for experimental purposes:
+###
+### null - a conduit that just logs a single message.
+### $(PERL_SUBDIR) - fires off a perl interpreter in a thread.
+### $(PYTHON_SUBDIR) - starts a python interpreter in a thread.
+###
diff --git a/kpilot/conduits/abbrowserconduit/CMakeLists.txt b/kpilot/conduits/abbrowserconduit/CMakeLists.txt
new file mode 100644
index 000000000..2459d1db9
--- /dev/null
+++ b/kpilot/conduits/abbrowserconduit/CMakeLists.txt
@@ -0,0 +1,46 @@
+include_directories(
+ ${CMAKE_CURRENT_BINARY_DIR}
+)
+
+set(conduit_abbrowser_SRCS
+ resolutionDialog.cc
+ abbrowser-factory.cc
+ abbrowser-setup.cc
+ kabcRecord.cc
+ abbrowser-conduit.cc
+)
+
+set(conduit_abbrowser_UIS
+ resolutionDialog_base.ui
+ kaddressbookConduit.ui
+)
+
+set(conduit_abbrowser_KCFGS
+ abbrowserSettings.kcfgc
+)
+
+kde3_add_kcfg_files(conduit_abbrowser_SRCS ${conduit_abbrowser_KCFGS})
+kde3_add_ui_files(conduit_abbrowser_SRCS ${conduit_abbrowser_UIS})
+kde3_automoc(${conduit_abbrowser_SRCS})
+add_library(conduit_address SHARED ${conduit_abbrowser_SRCS})
+target_link_libraries(conduit_address kabc_file kabc)
+set_target_properties(conduit_address PROPERTIES LOCATION ${KDE3_PLUGIN_INSTALL_DIR}
+ INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/lib
+ PREFIX ""
+)
+
+kde3_install_libtool_file(conduit_address)
+
+install(
+ TARGETS conduit_address
+ LIBRARY DESTINATION ${KDE3_PLUGIN_INSTALL_DIR}
+)
+
+install(
+ FILES abbrowser_conduit.desktop DESTINATION ${KDE3_SERVICES_DIR}
+)
+
+install(
+ FILES abbrowserconduit.kcfg DESTINATION ${KDE3_KCFG_DIR}
+)
+
diff --git a/kpilot/conduits/abbrowserconduit/KPilotCustomFieldEditor.ui b/kpilot/conduits/abbrowserconduit/KPilotCustomFieldEditor.ui
new file mode 100644
index 000000000..d4bb9078f
--- /dev/null
+++ b/kpilot/conduits/abbrowserconduit/KPilotCustomFieldEditor.ui
@@ -0,0 +1,276 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>KPilotCustomFields</class>
+<comment>This form lets you edit the custom fields synced from PalmOS handhelds by the addressbook conduit of KPilot.</comment>
+<author>Reinhold Kainhofer &lt;reinhold@kainhofer.com&gt;</author>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>KPILOT</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>461</width>
+ <height>409</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>KPilot Custom Fields</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>mCustomFieldsGroups</cstring>
+ </property>
+ <property name="title">
+ <string>KPilot Custom Fields</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>On your handheld, each address also provides four custom fields for your personal use. KPilot can sync these either to birthdate, URL, IM address, or just store them as a custom field on your PC with no special meaning. In the last case, you can change the values here. Note, however, that for all other settings the values entered here will have no effect.</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="3" column="0">
+ <property name="name">
+ <cstring>mCustom3Label</cstring>
+ </property>
+ <property name="text">
+ <string>Custom &amp;3:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>X_CUSTOM3</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Edit or enter the value of the third custom field here. Using KPilot, you can synchronize these values with the handheld's Address application custom fields.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="4" column="0">
+ <property name="name">
+ <cstring>mCustom4Label</cstring>
+ </property>
+ <property name="text">
+ <string>Custom &amp;4:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>X_CUSTOM3</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Edit or enter the value of the fourth custom field here. Using KPilot, you can synchronize these values with the handheld's Address application custom fields.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QLineEdit" row="3" column="1">
+ <property name="name">
+ <cstring>X_CUSTOM2</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Edit or enter the value of the third custom field here. Using KPilot, you can synchronize these values with the handheld's Address application custom fields.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QLineEdit" row="2" column="1">
+ <property name="name">
+ <cstring>X_CUSTOM1</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Edit or enter the value of the second custom field here. Using KPilot, you can synchronize these values with the handheld's Address application custom fields.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QLineEdit" row="4" column="1">
+ <property name="name">
+ <cstring>X_CUSTOM3</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Edit or enter the value of the fourth custom field here. Using KPilot, you can synchronize these values with the handheld's Address application custom fields.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="2" column="0">
+ <property name="name">
+ <cstring>mCustom2Label</cstring>
+ </property>
+ <property name="text">
+ <string>Custom &amp;2:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>X_CUSTOM2</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Edit or enter the value of the second custom field here. Using KPilot, you can synchronize these values with the handheld's Address application custom fields.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>mCustom1Label</cstring>
+ </property>
+ <property name="text">
+ <string>Custom &amp;1:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>X_CUSTOM1</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Edit or enter the value of the first custom field here. Using KPilot, you can synchronize these values with the handheld's Address application custom fields.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QLineEdit" row="1" column="1">
+ <property name="name">
+ <cstring>X_CUSTOM0</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>&lt;qt&gt;Edit or enter the value of the first custom field here. Using KPilot, you can synchronize these values with the handheld's Address application custom fields.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>mCustomFieldsExplanation</cstring>
+ </property>
+ <property name="text">
+ <string>If you let KPilot sync the handheld's custom fields as custom fields on the PC, you can change the values here. Note, however, that for all other settings the values entered here will have no effect.</string>
+ </property>
+ <property name="alignment">
+ <set>WordBreak|AlignVCenter</set>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>mMetaSyncGroup</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="title">
+ <string>KPilot's Private (meta-sync) Settings</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>mRecordIDLabel</cstring>
+ </property>
+ <property name="text">
+ <string>Record&amp;ID:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>X_RecordID</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="3">
+ <property name="name">
+ <cstring>mSyncFlagLabel</cstring>
+ </property>
+ <property name="text">
+ <string>Sync &amp;flag:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>X_Flag</cstring>
+ </property>
+ </widget>
+ <spacer row="1" column="5">
+ <property name="name">
+ <cstring>spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>41</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <spacer row="1" column="2">
+ <property name="name">
+ <cstring>spacer3</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>31</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLabel" row="0" column="0" rowspan="1" colspan="6">
+ <property name="name">
+ <cstring>mMetaSyncSettingsWarning</cstring>
+ </property>
+ <property name="text">
+ <string>These values indicate the state of the record for KPilot, and connect an entry on the handheld with an entry on the PC.
+Do NOT change these values: doing so will almost certainly result in data loss when you next do a sync.</string>
+ </property>
+ <property name="alignment">
+ <set>WordBreak|AlignVCenter</set>
+ </property>
+ </widget>
+ <widget class="QSpinBox" row="1" column="1">
+ <property name="name">
+ <cstring>X_RecordID</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="maxValue">
+ <number>2147483647</number>
+ </property>
+ </widget>
+ <widget class="QSpinBox" row="1" column="4">
+ <property name="name">
+ <cstring>X_Flag</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="maxValue">
+ <number>3</number>
+ </property>
+ </widget>
+ </grid>
+ </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>210</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+</widget>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/kpilot/conduits/abbrowserconduit/Makefile.am b/kpilot/conduits/abbrowserconduit/Makefile.am
new file mode 100644
index 000000000..6bb86c687
--- /dev/null
+++ b/kpilot/conduits/abbrowserconduit/Makefile.am
@@ -0,0 +1,24 @@
+INCLUDES= $(PISOCK_INCLUDE) -I$(top_srcdir)/kpilot/lib $(all_includes)
+
+kde_module_LTLIBRARIES = conduit_address.la
+
+conduit_address_la_SOURCES = \
+ resolutionDialog_base.ui \
+ kaddressbookConduit.ui \
+ abbrowserSettings.kcfgc \
+ resolutionDialog.cc \
+ abbrowser-factory.cc \
+ abbrowser-setup.cc \
+ kabcRecord.cc \
+ abbrowser-conduit.cc
+conduit_address_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries)
+conduit_address_la_LIBADD = ../../lib/libkpilot.la -lkabc -lkabc_file
+
+servicedir = $(kde_servicesdir)
+service_DATA = abbrowser_conduit.desktop
+kde_kcfg_DATA = abbrowserconduit.kcfg
+
+kabcustompagedir = $(kde_datadir)/kaddressbook/contacteditorpages
+kabcustompage_DATA = KPilotCustomFieldEditor.ui
+
+METASOURCES = AUTO
diff --git a/kpilot/conduits/abbrowserconduit/abbrowser-conduit.cc b/kpilot/conduits/abbrowserconduit/abbrowser-conduit.cc
new file mode 100644
index 000000000..bf038bb21
--- /dev/null
+++ b/kpilot/conduits/abbrowserconduit/abbrowser-conduit.cc
@@ -0,0 +1,1897 @@
+/* KPilot
+**
+** Copyright (C) 2000,2001 by Dan Pilone
+** Copyright (C) 2002-2003 by Reinhold Kainhofer
+** Copyright (C) 2007 by Adriaan de Groot <groot@kde.org>
+**
+** The abbrowser conduit copies addresses from the Pilot's address book to
+** the KDE addressbook maintained via the kabc library.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org.
+*/
+
+
+
+#include "options.h"
+
+#include <qtimer.h>
+#include <qtextcodec.h>
+#include <qfile.h>
+#include <qregexp.h>
+
+#include <kabc/stdaddressbook.h>
+#include <kabc/resourcefile.h>
+#include <kio/netaccess.h>
+#include <ksavefile.h>
+
+#include <pilotSerialDatabase.h>
+#include <pilotLocalDatabase.h>
+
+#include "resolutionDialog.h"
+#include "resolutionTable.h"
+#include "abbrowserSettings.h"
+#include "kabcRecord.h"
+
+#include "abbrowser-conduit.moc"
+
+// Something to allow us to check what revision
+// the modules are that make up a binary distribution.
+//
+//
+extern "C"
+{
+unsigned long version_conduit_address = Pilot::PLUGIN_API;
+}
+
+
+/* This is partly stolen from the boost libraries, partly from
+* "Modern C++ design" for doing compile time checks; we need
+* to make sure that the enum values in KABCSync:: and in the
+* AbbrowserSettings class are the same so that both interpret
+* configuration values the same way.
+*/
+template<bool> struct EnumerationMismatch;
+template<> struct EnumerationMismatch<true>{};
+
+#define CHECK_ENUM(a) (void)sizeof(EnumerationMismatch<((int)KABCSync::a)==((int)AbbrowserSettings::a)>)
+
+static inline void compile_time_check()
+{
+ // Mappings for other phone
+ CHECK_ENUM(eOtherPhone);
+ CHECK_ENUM(eOtherPhone);
+ CHECK_ENUM(eAssistant);
+ CHECK_ENUM(eBusinessFax);
+ CHECK_ENUM(eCarPhone);
+ CHECK_ENUM(eEmail2);
+ CHECK_ENUM(eHomeFax);
+ CHECK_ENUM(eTelex);
+ CHECK_ENUM(eTTYTTDPhone);
+
+ // Mappings for custom fields
+ CHECK_ENUM(eCustomField);
+ CHECK_ENUM(eCustomBirthdate);
+ CHECK_ENUM(eCustomURL);
+ CHECK_ENUM(eCustomIM);
+}
+
+inline int faxTypeOnPC()
+{
+ return KABC::PhoneNumber::Fax |
+ ( (AbbrowserSettings::pilotFax()==0) ?
+ KABC::PhoneNumber::Home :
+ KABC::PhoneNumber::Work );
+}
+
+
+using namespace KABC;
+
+/*********************************************************************
+ C O N S T R U C T O R
+ *********************************************************************/
+
+
+AbbrowserConduit::AbbrowserConduit(KPilotLink * o, const char *n, const QStringList & a):
+ ConduitAction(o, n, a),
+ aBook(0L),
+ fAddressAppInfo(0L),
+ addresseeMap(),
+ syncedIds(),
+ abiter(),
+ fTicket(0L),
+ fCreatedBook(false),
+ fBookResource(0L)
+{
+ FUNCTIONSETUP;
+ fConduitName=i18n("Addressbook");
+}
+
+
+
+AbbrowserConduit::~AbbrowserConduit()
+{
+ FUNCTIONSETUP;
+
+ if (fTicket)
+ {
+ DEBUGKPILOT << fname << ": Releasing ticket" << endl;
+ aBook->releaseSaveTicket(fTicket);
+ fTicket=0L;
+ }
+
+ _cleanupAddressBookPointer();
+ // unused function warnings.
+ compile_time_check();
+}
+
+
+
+/*********************************************************************
+ L O A D I N G T H E D A T A
+ *********************************************************************/
+
+
+
+/* Builds the map which links record ids to uid's of Addressee
+*/
+void AbbrowserConduit::_mapContactsToPilot(QMap < recordid_t, QString > &idContactMap)
+{
+ FUNCTIONSETUP;
+
+ idContactMap.clear();
+
+ for(AddressBook::Iterator contactIter = aBook->begin();
+ contactIter != aBook->end(); ++contactIter)
+ {
+ Addressee aContact = *contactIter;
+ QString recid = aContact.custom(KABCSync::appString, KABCSync::idString);
+ if(!recid.isEmpty())
+ {
+ recordid_t id = recid.toULong();
+ // safety check: make sure that we don't already have a map for this pilot id.
+ // if we do (this can come from a copy/paste in kaddressbook, etc.), then we need
+ // to reset our Addressee so that we can assign him a new pilot Id later and sync
+ // him properly. if we don't do this, we'll lose one of these on the pilot.
+ if (!idContactMap.contains(id))
+ {
+ idContactMap.insert(id, aContact.uid());
+ }
+ else
+ {
+ DEBUGKPILOT << fname << ": found duplicate pilot key: ["
+ << id << "], removing pilot id from addressee: ["
+ << aContact.realName() << "]" << endl;
+ aContact.removeCustom(KABCSync::appString, KABCSync::idString);
+ aBook->insertAddressee(aContact);
+ abChanged = true;
+ }
+ }
+ }
+ DEBUGKPILOT << fname << ": Loaded " << idContactMap.size() <<
+ " addresses from the addressbook. " << endl;
+}
+
+
+
+bool AbbrowserConduit::_prepare()
+{
+ FUNCTIONSETUP;
+
+ readConfig();
+ syncedIds.clear();
+ pilotindex = 0;
+
+ return true;
+}
+
+
+
+void AbbrowserConduit::readConfig()
+{
+ FUNCTIONSETUP;
+ AbbrowserSettings::self()->readConfig();
+
+ // Conflict page
+ SyncAction::ConflictResolution res = (SyncAction::ConflictResolution)AbbrowserSettings::conflictResolution();
+ setConflictResolution(res);
+
+ DEBUGKPILOT << fname
+ << ": Reading addressbook "
+ << ( AbbrowserSettings::addressbookType() == AbbrowserSettings::eAbookFile ?
+ AbbrowserSettings::fileName() : CSL1("Standard") )
+ << endl;
+ DEBUGKPILOT << fname
+ << ": "
+ << " fConflictResolution=" << getConflictResolution()
+ << " fArchive=" << AbbrowserSettings::archiveDeleted()
+ << " fFirstTime=" << isFirstSync()
+ << endl;
+ DEBUGKPILOT << fname
+ << ": "
+ << " fPilotStreetHome=" << AbbrowserSettings::pilotStreet()
+ << " fPilotFaxHome=" << AbbrowserSettings::pilotFax()
+ << " eCustom[0]=" << AbbrowserSettings::custom0()
+ << " eCustom[1]=" << AbbrowserSettings::custom1()
+ << " eCustom[2]=" << AbbrowserSettings::custom2()
+ << " eCustom[3]=" << AbbrowserSettings::custom3()
+ << endl;
+}
+
+
+
+bool isDeleted(const PilotAddress *addr)
+{
+ if (!addr)
+ {
+ return true;
+ }
+ if (addr->isDeleted() && !addr->isArchived())
+ {
+ return true;
+ }
+ if (addr->isArchived())
+ {
+ return !AbbrowserSettings::archiveDeleted();
+ }
+ return false;
+}
+
+bool isArchived(const PilotAddress *addr)
+{
+ if (addr && addr->isArchived())
+ {
+ return AbbrowserSettings::archiveDeleted();
+ }
+ else
+ {
+ return false;
+ }
+}
+
+
+
+bool AbbrowserConduit::_loadAddressBook()
+{
+ FUNCTIONSETUP;
+
+ startTickle();
+ switch ( AbbrowserSettings::addressbookType() )
+ {
+ case AbbrowserSettings::eAbookResource:
+ DEBUGKPILOT<<"Loading standard addressbook"<<endl;
+ aBook = StdAddressBook::self( true );
+ fCreatedBook=false;
+ break;
+ case AbbrowserSettings::eAbookFile:
+ { // initialize the abook with the given file
+ DEBUGKPILOT<<"Loading custom addressbook"<<endl;
+ KURL kurl(AbbrowserSettings::fileName());
+ if(!KIO::NetAccess::download(AbbrowserSettings::fileName(), fABookFile, 0L) &&
+ !kurl.isLocalFile())
+ {
+ emit logError(i18n("You chose to sync with the file \"%1\", which "
+ "cannot be opened. Please make sure to supply a "
+ "valid file name in the conduit's configuration dialog. "
+ "Aborting the conduit.").arg(AbbrowserSettings::fileName()));
+ KIO::NetAccess::removeTempFile(fABookFile);
+ stopTickle();
+ return false;
+ }
+
+ aBook = new AddressBook();
+ if (!aBook)
+ {
+ stopTickle();
+ return false;
+ }
+ fBookResource = new ResourceFile(fABookFile, CSL1("vcard") );
+
+ bool r = aBook->addResource( fBookResource );
+ if ( !r )
+ {
+ DEBUGKPILOT << "Unable to open resource for file " << fABookFile << endl;
+ KPILOT_DELETE( aBook );
+ stopTickle();
+ return false;
+ }
+ fCreatedBook=true;
+ break;
+ }
+ default: break;
+ }
+ // find out if this can fail for reasons other than a non-existent
+ // vcf file. If so, how can I determine if the missing file was the problem
+ // or something more serious:
+ if ( !aBook || !aBook->load() )
+ {
+ // Something went wrong, so tell the user and return false to exit the conduit
+ emit logError(i18n("Unable to initialize and load the addressbook for the sync.") );
+ addSyncLogEntry(i18n("Unable to initialize and load the addressbook for the sync.") );
+ WARNINGKPILOT << "Unable to initialize the addressbook for the sync." << endl;
+ _cleanupAddressBookPointer();
+ stopTickle();
+ return false;
+ }
+ abChanged = false;
+
+ fTicket=aBook->requestSaveTicket();
+ if (!fTicket)
+ {
+ WARNINGKPILOT << "Unable to lock addressbook for writing " << endl;
+ emit logError(i18n("Unable to lock addressbook for writing. Can't sync!"));
+ addSyncLogEntry(i18n("Unable to lock addressbook for writing. Can't sync!"));
+ _cleanupAddressBookPointer();
+ stopTickle();
+ return false;
+ }
+
+ fCtrPC->setStartCount(aBook->allAddressees().count());
+
+ // get the addresseMap which maps Pilot unique record(address) id's to
+ // a Abbrowser Addressee; allows for easy lookup and comparisons
+ if(aBook->begin() == aBook->end())
+ {
+ setFirstSync( true );
+ }
+ else
+ {
+ _mapContactsToPilot(addresseeMap);
+ }
+ stopTickle();
+ return(aBook != 0L);
+}
+
+bool AbbrowserConduit::_saveAddressBook()
+{
+ FUNCTIONSETUP;
+
+ bool saveSuccessful = false;
+
+ fCtrPC->setEndCount(aBook->allAddressees().count());
+
+ Q_ASSERT(fTicket);
+
+ if (abChanged)
+ {
+ saveSuccessful = aBook->save(fTicket);
+ }
+ else
+ {
+ DEBUGKPILOT << fname
+ << "Addressbook not changed, no need to save it" << endl;
+ }
+ // XXX: KDE4: release ticket in all cases (save no longer releases it)
+ if ( !saveSuccessful ) // didn't save, delete ticket manually
+ {
+ aBook->releaseSaveTicket(fTicket);
+ }
+ fTicket=0L;
+
+ if ( AbbrowserSettings::addressbookType()!= AbbrowserSettings::eAbookResource )
+ {
+ KURL kurl(AbbrowserSettings::fileName());
+ if(!kurl.isLocalFile())
+ {
+ DEBUGKPILOT << fname << "Deleting local addressbook tempfile" << endl;
+ if(!KIO::NetAccess::upload(fABookFile, AbbrowserSettings::fileName(), 0L)) {
+ emit logError(i18n("An error occurred while uploading \"%1\". You can try to upload "
+ "the temporary local file \"%2\" manually")
+ .arg(AbbrowserSettings::fileName()).arg(fABookFile));
+ }
+ else {
+ KIO::NetAccess::removeTempFile(fABookFile);
+ }
+ QFile backup(fABookFile + CSL1("~"));
+ backup.remove();
+ }
+
+ }
+
+ // now try to remove the resource from the addressbook...
+ if (fBookResource)
+ {
+ bool r = aBook->removeResource( fBookResource );
+ if ( !r )
+ {
+ DEBUGKPILOT << fname <<": Unable to close resource." << endl;
+ }
+ }
+
+ return saveSuccessful;
+}
+
+
+
+void AbbrowserConduit::_getAppInfo()
+{
+ FUNCTIONSETUP;
+
+ delete fAddressAppInfo;
+ fAddressAppInfo = new PilotAddressInfo(fDatabase);
+ fAddressAppInfo->dump();
+}
+
+void AbbrowserConduit::_setAppInfo()
+{
+ FUNCTIONSETUP;
+ if (fDatabase) fAddressAppInfo->writeTo(fDatabase);
+ if (fLocalDatabase) fAddressAppInfo->writeTo(fLocalDatabase);
+}
+
+
+void AbbrowserConduit::_cleanupAddressBookPointer()
+{
+ if (fCreatedBook)
+ {
+ KPILOT_DELETE(aBook);
+ fCreatedBook=false;
+ }
+ else
+ {
+ aBook=0L;
+ }
+}
+
+
+
+
+/*********************************************************************
+ D E B U G O U T P U T
+ *********************************************************************/
+
+
+
+
+
+void AbbrowserConduit::showPilotAddress(const PilotAddress *pilotAddress)
+{
+ FUNCTIONSETUPL(3);
+ if (debug_level < 3)
+ {
+ return;
+ }
+ if (!pilotAddress)
+ {
+ DEBUGKPILOT<< fname << "| EMPTY"<<endl;
+ return;
+ }
+ DEBUGKPILOT << fname << "\n"
+ << pilotAddress->getTextRepresentation(
+ fAddressAppInfo,Qt::PlainText) << endl;
+}
+
+
+void AbbrowserConduit::showAddresses(
+ const Addressee &pcAddr,
+ const PilotAddress *backupAddr,
+ const PilotAddress *palmAddr)
+{
+ FUNCTIONSETUPL(3);
+ if (debug_level >= 3)
+ {
+ DEBUGKPILOT << fname << "abEntry:" << endl;
+ KABCSync::showAddressee(pcAddr);
+ DEBUGKPILOT << fname << "pilotAddress:" << endl;
+ showPilotAddress(palmAddr);
+ DEBUGKPILOT << fname << "backupAddress:" << endl;
+ showPilotAddress(backupAddr);
+ DEBUGKPILOT << fname << "------------------------------------------------" << endl;
+ }
+}
+
+
+
+/*********************************************************************
+ S Y N C S T R U C T U R E
+ *********************************************************************/
+
+
+
+/* virtual */ bool AbbrowserConduit::exec()
+{
+ FUNCTIONSETUP;
+
+ _prepare();
+
+ bool retrieved = false;
+ if(!openDatabases(CSL1("AddressDB"), &retrieved))
+ {
+ emit logError(i18n("Unable to open the addressbook databases on the handheld."));
+ return false;
+ }
+ setFirstSync( retrieved );
+
+ _getAppInfo();
+
+ // Local block
+ {
+ QString dbpath = fLocalDatabase->dbPathName();
+ DEBUGKPILOT << fname << ": Local database path " << dbpath << endl;
+ }
+
+ if ( syncMode().isTest() )
+ {
+ QTimer::singleShot(0, this, SLOT(slotTestRecord()));
+ return true;
+ }
+
+ if(!_loadAddressBook())
+ {
+ emit logError(i18n("Unable to open the addressbook."));
+ return false;
+ }
+ setFirstSync( isFirstSync() || (aBook->begin() == aBook->end()) );
+
+ DEBUGKPILOT << fname << ": First sync now " << isFirstSync()
+ << " and addressbook is "
+ << ((aBook->begin() == aBook->end()) ? "" : "non-")
+ << "empty." << endl;
+
+ // perform syncing from palm to abbrowser
+ // iterate through all records in palm pilot
+
+ DEBUGKPILOT << fname << ": fullsync=" << isFullSync() << ", firstSync=" << isFirstSync() << endl;
+ DEBUGKPILOT << fname << ": "
+ << "syncDirection=" << syncMode().name() << ", "
+ << "archive = " << AbbrowserSettings::archiveDeleted() << endl;
+ DEBUGKPILOT << fname << ": conflictRes="<< getConflictResolution() << endl;
+ DEBUGKPILOT << fname << ": PilotStreetHome=" << AbbrowserSettings::pilotStreet() << ", PilotFaxHOme" << AbbrowserSettings::pilotFax() << endl;
+
+ if (!isFirstSync())
+ {
+ allIds=fDatabase->idList();
+ }
+
+ QValueVector<int> v(4);
+ v[0] = AbbrowserSettings::custom0();
+ v[1] = AbbrowserSettings::custom1();
+ v[2] = AbbrowserSettings::custom2();
+ v[3] = AbbrowserSettings::custom3();
+
+ fSyncSettings.setCustomMapping(v);
+ fSyncSettings.setFieldForOtherPhone(AbbrowserSettings::pilotOther());
+ fSyncSettings.setDateFormat(AbbrowserSettings::customDateFormat());
+ fSyncSettings.setPreferHome(AbbrowserSettings::pilotStreet()==0);
+ fSyncSettings.setFaxTypeOnPC(faxTypeOnPC());
+
+ /* Note:
+ if eCopyPCToHH or eCopyHHToPC, first sync everything, then lookup
+ those entries on the receiving side that are not yet syncced and delete
+ them. Use slotDeleteUnsyncedPCRecords and slotDeleteUnsyncedHHRecords
+ for this, and no longer purge the whole addressbook before the sync to
+ prevent data loss in case of connection loss. */
+
+ QTimer::singleShot(0, this, SLOT(slotPalmRecToPC()));
+
+ return true;
+}
+
+
+
+void AbbrowserConduit::slotPalmRecToPC()
+{
+ FUNCTIONSETUP;
+ PilotRecord *palmRec = 0L, *backupRec = 0L;
+
+ if ( syncMode() == SyncMode::eCopyPCToHH )
+ {
+ DEBUGKPILOT << fname << ": Done; change to PCtoHH phase." << endl;
+ abiter = aBook->begin();
+ QTimer::singleShot(0, this, SLOT(slotPCRecToPalm()));
+ return;
+ }
+
+ if(isFullSync())
+ {
+ palmRec = fDatabase->readRecordByIndex(pilotindex++);
+ }
+ else
+ {
+ palmRec = fDatabase->readNextModifiedRec();
+ }
+
+ // no record means we're done going in this direction, so switch to
+ // PC->Palm
+ if(!palmRec)
+ {
+ abiter = aBook->begin();
+ QTimer::singleShot(0, this, SLOT(slotPCRecToPalm()));
+ return;
+ }
+
+ // already synced, so skip:
+ if(syncedIds.contains(palmRec->id()))
+ {
+ KPILOT_DELETE(palmRec);
+ QTimer::singleShot(0, this, SLOT(slotPalmRecToPC()));
+ return;
+ }
+
+ backupRec = fLocalDatabase->readRecordById(palmRec->id());
+ PilotRecord*compareRec=(backupRec)?(backupRec):(palmRec);
+ Addressee e = _findMatch(PilotAddress(compareRec));
+
+ PilotAddress*backupAddr=0L;
+ if (backupRec)
+ {
+ backupAddr=new PilotAddress(backupRec);
+ }
+
+ PilotAddress*palmAddr=0L;
+ if (palmRec)
+ {
+ palmAddr=new PilotAddress(palmRec);
+ }
+
+ syncAddressee(e, backupAddr, palmAddr);
+
+ syncedIds.append(palmRec->id());
+ KPILOT_DELETE(palmAddr);
+ KPILOT_DELETE(backupAddr);
+ KPILOT_DELETE(palmRec);
+ KPILOT_DELETE(backupRec);
+
+ QTimer::singleShot(0, this, SLOT(slotPalmRecToPC()));
+}
+
+
+
+void AbbrowserConduit::slotPCRecToPalm()
+{
+ FUNCTIONSETUP;
+
+ if ( (syncMode()==SyncMode::eCopyHHToPC) ||
+ abiter == aBook->end() || (*abiter).isEmpty() )
+ {
+ DEBUGKPILOT << fname << ": Done; change to delete records." << endl;
+ pilotindex = 0;
+ QTimer::singleShot(0, this, SLOT(slotDeletedRecord()));
+ return;
+ }
+
+ PilotRecord *palmRec=0L, *backupRec=0L;
+ Addressee ad = *abiter;
+
+ abiter++;
+
+ // If marked as archived, don't sync!
+ if (KABCSync::isArchived(ad))
+ {
+ DEBUGKPILOT << fname << ": address with id " << ad.uid() <<
+ " marked archived, so don't sync." << endl;
+ QTimer::singleShot(0, this, SLOT(slotPCRecToPalm()));
+ return;
+ }
+
+
+ QString recID(ad.custom(KABCSync::appString, KABCSync::idString));
+ bool ok;
+ recordid_t rid = recID.toLong(&ok);
+ if (recID.isEmpty() || !ok || !rid)
+ {
+ DEBUGKPILOT << fname << ": This is a new record." << endl;
+ // it's a new item(no record ID and not inserted by the Palm -> PC sync), so add it
+ syncAddressee(ad, 0L, 0L);
+ QTimer::singleShot(0, this, SLOT(slotPCRecToPalm()));
+ return;
+ }
+
+ // look into the list of already synced record ids to see if the addressee hasn't already been synced
+ if (syncedIds.contains(rid))
+ {
+ DEBUGKPILOT << ": address with id " << rid << " already synced." << endl;
+ QTimer::singleShot(0, this, SLOT(slotPCRecToPalm()));
+ return;
+ }
+
+
+ backupRec = fLocalDatabase->readRecordById(rid);
+ // only update if no backup record or the backup record is not equal to the addressee
+
+ PilotAddress*backupAddr=0L;
+ if (backupRec)
+ {
+ backupAddr=new PilotAddress(backupRec);
+ }
+ if(!backupRec || isFirstSync() || !_equal(backupAddr, ad) )
+ {
+ DEBUGKPILOT << fname << ": Updating entry." << endl;
+ palmRec = fDatabase->readRecordById(rid);
+ PilotAddress *palmAddr = 0L;
+ if (palmRec)
+ {
+ palmAddr = new PilotAddress(palmRec);
+ }
+ else
+ {
+ DEBUGKPILOT << fname << ": No HH record with id " << rid << endl;
+ }
+ syncAddressee(ad, backupAddr, palmAddr);
+ // update the id just in case it changed
+ if (palmRec) rid=palmRec->id();
+ KPILOT_DELETE(palmRec);
+ KPILOT_DELETE(palmAddr);
+ }
+ else
+ {
+ DEBUGKPILOT << fname << ": Entry not updated." << endl;
+ }
+ KPILOT_DELETE(backupAddr);
+ KPILOT_DELETE(backupRec);
+
+ DEBUGKPILOT << fname << ": adding id:["<< rid << "] to syncedIds." << endl;
+
+ syncedIds.append(rid);
+ // done with the sync process, go on with the next one:
+ QTimer::singleShot(0, this, SLOT(slotPCRecToPalm()));
+}
+
+
+
+void AbbrowserConduit::slotDeletedRecord()
+{
+ FUNCTIONSETUP;
+
+ PilotRecord *backupRec = fLocalDatabase->readRecordByIndex(pilotindex++);
+ if(!backupRec || isFirstSync() )
+ {
+ KPILOT_DELETE(backupRec);
+ QTimer::singleShot(0, this, SLOT(slotDeleteUnsyncedPCRecords()));
+ return;
+ }
+
+ recordid_t id = backupRec->id();
+
+ QString uid = addresseeMap[id];
+ Addressee e = aBook->findByUid(uid);
+
+ DEBUGKPILOT << fname << ": now looking at palm id: ["
+ << id << "], kabc uid: [" << uid << "]." << endl;
+
+ PilotAddress*backupAddr=0L;
+ if (backupRec)
+ {
+ backupAddr=new PilotAddress(backupRec);
+ }
+ PilotRecord*palmRec=fDatabase->readRecordById(id);
+
+ if ( e.isEmpty() )
+ {
+ DEBUGKPILOT << fname << ": no Addressee found for this id." << endl;
+ DEBUGKPILOT << fname << "\n"
+ << backupAddr->getTextRepresentation(
+ fAddressAppInfo,Qt::PlainText) << endl;
+
+ if (palmRec) {
+ DEBUGKPILOT << fname << ": deleting from database on palm." << endl;
+ fDatabase->deleteRecord(id);
+ fCtrHH->deleted();
+ }
+ DEBUGKPILOT << fname << ": deleting from backup database." << endl;
+ fLocalDatabase->deleteRecord(id);
+
+ // because we just deleted a record, we need to go back one
+ pilotindex--;
+ }
+
+ KPILOT_DELETE(palmRec);
+ KPILOT_DELETE(backupAddr);
+ KPILOT_DELETE(backupRec);
+ QTimer::singleShot(0, this, SLOT(slotDeletedRecord()));
+}
+
+
+
+void AbbrowserConduit::slotDeleteUnsyncedPCRecords()
+{
+ FUNCTIONSETUP;
+ if ( syncMode()==SyncMode::eCopyHHToPC )
+ {
+ QStringList uids;
+ RecordIDList::iterator it;
+ QString uid;
+ for ( it = syncedIds.begin(); it != syncedIds.end(); ++it)
+ {
+ uid=addresseeMap[*it];
+ if (!uid.isEmpty()) uids.append(uid);
+ }
+ // TODO: Does this speed up anything?
+ // qHeapSort( uids );
+ AddressBook::Iterator abit;
+ for (abit = aBook->begin(); abit != aBook->end(); ++abit)
+ {
+ if (!uids.contains((*abit).uid()))
+ {
+ DEBUGKPILOT<<"Deleting addressee "<<(*abit).realName()<<" from PC (is not on HH, and syncing with HH->PC direction)"<<endl;
+ abChanged = true;
+ // TODO: Can I really remove the current iterator???
+ aBook->removeAddressee(*abit);
+ fCtrPC->deleted();
+ }
+ }
+ }
+ QTimer::singleShot(0, this, SLOT(slotDeleteUnsyncedHHRecords()));
+}
+
+
+
+void AbbrowserConduit::slotDeleteUnsyncedHHRecords()
+{
+ FUNCTIONSETUP;
+ if ( syncMode()==SyncMode::eCopyPCToHH )
+ {
+ RecordIDList ids=fDatabase->idList();
+ RecordIDList::iterator it;
+ for ( it = ids.begin(); it != ids.end(); ++it )
+ {
+ if (!syncedIds.contains(*it))
+ {
+ DEBUGKPILOT<<"Deleting record with ID "<<*it<<" from handheld (is not on PC, and syncing with PC->HH direction)"<<endl;
+ fDatabase->deleteRecord(*it);
+ fCtrHH->deleted();
+ fLocalDatabase->deleteRecord(*it);
+ }
+ }
+ }
+ QTimer::singleShot(0, this, SLOT(slotCleanup()));
+}
+
+
+void AbbrowserConduit::slotCleanup()
+{
+ FUNCTIONSETUP;
+
+ // Set the appInfoBlock, just in case the category labels changed
+ _setAppInfo();
+ if(fDatabase)
+ {
+ fDatabase->resetSyncFlags();
+ fDatabase->cleanup();
+ }
+ if(fLocalDatabase)
+ {
+ fLocalDatabase->resetSyncFlags();
+ fLocalDatabase->cleanup();
+ }
+
+ // Write out the sync maps
+ QString syncFile = fLocalDatabase->dbPathName() + CSL1(".sync");
+ DEBUGKPILOT << fname << ": Writing sync map to " << syncFile << endl;
+ KSaveFile map( syncFile );
+ if ( map.status() == 0 )
+ {
+ DEBUGKPILOT << fname << ": Writing sync map ..." << endl;
+ (*map.dataStream()) << addresseeMap ;
+ map.close();
+ }
+ // This also picks up errors from map.close()
+ if ( map.status() != 0 )
+ {
+ WARNINGKPILOT << "Could not make backup of sync map." << endl;
+ }
+
+ _saveAddressBook();
+ delayDone();
+}
+
+
+
+/*********************************************************************
+ G E N E R A L S Y N C F U N C T I O N
+ These functions modify the Handheld and the addressbook
+ *********************************************************************/
+
+
+
+bool AbbrowserConduit::syncAddressee(Addressee &pcAddr, PilotAddress*backupAddr,
+ PilotAddress*palmAddr)
+{
+ FUNCTIONSETUP;
+ showAddresses(pcAddr, backupAddr, palmAddr);
+
+ if ( syncMode() == SyncMode::eCopyPCToHH )
+ {
+ if (pcAddr.isEmpty())
+ {
+ return _deleteAddressee(pcAddr, backupAddr, palmAddr);
+ }
+ else
+ {
+ return _copyToHH(pcAddr, backupAddr, palmAddr);
+ }
+ }
+
+ if ( syncMode() == SyncMode::eCopyHHToPC )
+ {
+ if (!palmAddr)
+ {
+ return _deleteAddressee(pcAddr, backupAddr, palmAddr);
+ }
+ else
+ {
+ return _copyToPC(pcAddr, backupAddr, palmAddr);
+ }
+ }
+
+ if ( !backupAddr || isFirstSync() )
+ {
+ DEBUGKPILOT<< fname << ": Special case: no backup." << endl;
+ /*
+ Resolution matrix (0..does not exist, E..exists, D..deleted flag set, A..archived):
+ HH PC | Resolution
+ ------------------------------------------------------------
+ 0 A | -
+ 0 E | PC -> HH, reset ID if not set correctly
+ D 0 | delete (error, should never occur!!!)
+ D E | CR (ERROR)
+ E/A 0 | HH -> PC
+ E/A E/A| merge/CR
+ */
+ if (!palmAddr && KABCSync::isArchived(pcAddr) )
+ {
+ return true;
+ }
+ else if (!palmAddr && !pcAddr.isEmpty())
+ {
+ DEBUGKPILOT << fname << ": case: 1a"<<endl;
+ // PC->HH
+ bool res=_copyToHH(pcAddr, 0L, 0L);
+ return res;
+ }
+ else if (!palmAddr && pcAddr.isEmpty())
+ {
+ DEBUGKPILOT << fname << ": case: 1b"<<endl;
+ // everything's empty -> ERROR
+ return false;
+ }
+ else if ( (isDeleted(palmAddr) || isArchived(palmAddr)) && pcAddr.isEmpty())
+ {
+ DEBUGKPILOT << fname << ": case: 1c"<<endl;
+ if (isArchived(palmAddr))
+ return _copyToPC(pcAddr, 0L, palmAddr);
+ else
+ // this happens if you add a record on the handheld and delete it again before you do the next sync
+ return _deleteAddressee(pcAddr, 0L, palmAddr);
+ }
+ else if ((isDeleted(palmAddr)||isArchived(palmAddr)) && !pcAddr.isEmpty())
+ {
+ DEBUGKPILOT << fname << ": case: 1d"<<endl;
+ // CR (ERROR)
+ return _smartMergeAddressee(pcAddr, 0L, palmAddr);
+ }
+ else if (pcAddr.isEmpty())
+ {
+ DEBUGKPILOT << fname << ": case: 1e"<<endl;
+ // HH->PC
+ return _copyToPC(pcAddr, 0L, palmAddr);
+ }
+ else
+ {
+ DEBUGKPILOT << fname << ": case: 1f"<<endl;
+ // Conflict Resolution
+ return _smartMergeAddressee(pcAddr, 0L, palmAddr);
+ }
+ } // !backupAddr
+ else
+ {
+ DEBUGKPILOT << fname << ": case: 2"<<endl;
+ /*
+ Resolution matrix:
+ 1) if HH.(empty| (deleted &! archived) ) -> { if (PC==B) -> delete, else -> CR }
+ if HH.archied -> {if (PC==B) -> copyToPC, else -> CR }
+ if PC.empty -> { if (HH==B) -> delete, else -> CR }
+ if PC.archived -> {if (HH==B) -> delete on HH, else CR }
+ 2) if PC==HH -> { update B, update ID of PC if needed }
+ 3) if PC==B -> { HH!=PC, thus HH modified, so copy HH->PC }
+ if HH==B -> { PC!=HH, thus PC modified, so copy PC->HH }
+ 4) else: all three addressees are different -> CR
+ */
+
+ if (!palmAddr || isDeleted(palmAddr) )
+ {
+ DEBUGKPILOT << fname << ": case: 2a"<<endl;
+ if (_equal(backupAddr, pcAddr) || pcAddr.isEmpty())
+ {
+ return _deleteAddressee(pcAddr, backupAddr, 0L);
+ }
+ else
+ {
+ return _smartMergeAddressee(pcAddr, backupAddr, 0L);
+ }
+ }
+ else if (pcAddr.isEmpty())
+ {
+ DEBUGKPILOT << fname << ": case: 2b"<<endl;
+ if (*palmAddr == *backupAddr)
+ {
+ return _deleteAddressee(pcAddr, backupAddr, palmAddr);
+ }
+ else
+ {
+ return _smartMergeAddressee(pcAddr, backupAddr, palmAddr);
+ }
+ }
+ else if (_equal(palmAddr, pcAddr))
+ {
+ DEBUGKPILOT << fname << ": case: 2c"<<endl;
+ // update Backup, update ID of PC if neededd
+ return _writeBackup(palmAddr);
+ }
+ else if (_equal(backupAddr, pcAddr))
+ {
+ DEBUGKPILOT << fname << ": case: 2d"<<endl;
+ DEBUGKPILOT << fname << ": Flags: "<<palmAddr->attributes()<<", isDeleted="<<
+ isDeleted(palmAddr)<<", isArchived="<<isArchived(palmAddr)<<endl;
+ if (isDeleted(palmAddr))
+ return _deleteAddressee(pcAddr, backupAddr, palmAddr);
+ else
+ return _copyToPC(pcAddr, backupAddr, palmAddr);
+ }
+ else if (*palmAddr == *backupAddr)
+ {
+ DEBUGKPILOT << fname << ": case: 2e"<<endl;
+ return _copyToHH(pcAddr, backupAddr, palmAddr);
+ }
+ else
+ {
+ DEBUGKPILOT << fname << ": case: 2f"<<endl;
+ // CR, since all are different
+ return _smartMergeAddressee(pcAddr, backupAddr, palmAddr);
+ }
+ } // backupAddr
+ return false;
+}
+
+
+
+bool AbbrowserConduit::_copyToHH(Addressee &pcAddr, PilotAddress*backupAddr,
+ PilotAddress*palmAddr)
+{
+ FUNCTIONSETUP;
+
+ if (pcAddr.isEmpty()) return false;
+ PilotAddress*paddr=palmAddr;
+ bool paddrcreated=false;
+ if (!paddr)
+ {
+ paddr=new PilotAddress();
+ paddrcreated=true;
+ fCtrHH->created();
+ }
+ else
+ {
+ fCtrHH->updated();
+ }
+ KABCSync::copy(*paddr, pcAddr, *fAddressAppInfo, fSyncSettings);
+
+ DEBUGKPILOT << fname << "palmAddr->id=" << paddr->id()
+ << ", pcAddr.ID=" << pcAddr.custom(KABCSync::appString, KABCSync::idString) << endl;
+
+ if(_savePalmAddr(paddr, pcAddr))
+ {
+ _savePCAddr(pcAddr, backupAddr, paddr);
+ }
+ if (paddrcreated) KPILOT_DELETE(paddr);
+ return true;
+}
+
+
+
+bool AbbrowserConduit::_copyToPC(Addressee &pcAddr, PilotAddress*backupAddr,
+ PilotAddress*palmAddr)
+{
+ FUNCTIONSETUP;
+ if (!palmAddr)
+ {
+ return false;
+ }
+ // keep track of CUD's...
+ if (pcAddr.isEmpty())
+ {
+ fCtrPC->created();
+ }
+ else
+ {
+ fCtrPC->updated();
+ }
+ showPilotAddress(palmAddr);
+
+ KABCSync::copy(pcAddr, *palmAddr, *fAddressAppInfo, fSyncSettings);
+ if (isArchived(palmAddr))
+ {
+ KABCSync::makeArchived(pcAddr);
+ }
+
+ _savePCAddr(pcAddr, backupAddr, palmAddr);
+ _writeBackup(palmAddr);
+ return true;
+}
+
+
+
+bool AbbrowserConduit::_writeBackup(PilotAddress *backup)
+{
+ FUNCTIONSETUP;
+ if (!backup) return false;
+
+ showPilotAddress(backup);
+
+ PilotRecord *pilotRec = backup->pack();
+ fLocalDatabase->writeRecord(pilotRec);
+ KPILOT_DELETE(pilotRec);
+ return true;
+}
+
+
+
+bool AbbrowserConduit::_deleteAddressee(Addressee &pcAddr, PilotAddress*backupAddr,
+ PilotAddress*palmAddr)
+{
+ FUNCTIONSETUP;
+
+ if (palmAddr)
+ {
+ if (!syncedIds.contains(palmAddr->id())) {
+ DEBUGKPILOT << fname << ": adding id:["<< palmAddr->id() << "] to syncedIds." << endl;
+ syncedIds.append(palmAddr->id());
+ }
+ fDatabase->deleteRecord(palmAddr->id());
+ fCtrHH->deleted();
+ fLocalDatabase->deleteRecord(palmAddr->id());
+ }
+ else if (backupAddr)
+ {
+ if (!syncedIds.contains(backupAddr->id())) {
+ DEBUGKPILOT << fname << ": adding id:["<< backupAddr->id() << "] to syncedIds." << endl;
+ syncedIds.append(backupAddr->id());
+ }
+ fLocalDatabase->deleteRecord(backupAddr->id());
+ }
+ if (!pcAddr.isEmpty())
+ {
+ DEBUGKPILOT << fname << " removing " << pcAddr.formattedName() << endl;
+ abChanged = true;
+ aBook->removeAddressee(pcAddr);
+ fCtrPC->deleted();
+ }
+ return true;
+}
+
+
+
+/*********************************************************************
+ l o w - l e v e l f u n c t i o n s f o r
+ adding / removing palm/pc records
+ *********************************************************************/
+
+
+
+bool AbbrowserConduit::_savePalmAddr(PilotAddress *palmAddr, Addressee &pcAddr)
+{
+ FUNCTIONSETUP;
+
+ DEBUGKPILOT << fname << ": Saving to pilot " << palmAddr->id()
+ << " " << palmAddr->getField(entryFirstname)
+ << " " << palmAddr->getField(entryLastname)<< endl;
+
+ PilotRecord *pilotRec = palmAddr->pack();
+ DEBUGKPILOT << fname << ": record with id=" << pilotRec->id()
+ << " len=" << pilotRec->size() << endl;
+ recordid_t pilotId = fDatabase->writeRecord(pilotRec);
+ DEBUGKPILOT << fname << ": Wrote "<<pilotId<<": ID="<<pilotRec->id()<<endl;
+ fLocalDatabase->writeRecord(pilotRec);
+ KPILOT_DELETE(pilotRec);
+
+ // pilotId == 0 if using local db, so don't overwrite the valid id
+ if(pilotId != 0)
+ {
+ palmAddr->setID(pilotId);
+ if (!syncedIds.contains(pilotId)) {
+ DEBUGKPILOT << fname << ": adding id:["<< pilotId << "] to syncedIds." << endl;
+ syncedIds.append(pilotId);
+ }
+ }
+
+ recordid_t abId = 0;
+ abId = pcAddr.custom(KABCSync::appString, KABCSync::idString).toUInt();
+ if(abId != pilotId)
+ {
+ pcAddr.insertCustom(KABCSync::appString, KABCSync::idString, QString::number(pilotId));
+ return true;
+ }
+
+ return false;
+}
+
+
+
+bool AbbrowserConduit::_savePCAddr(Addressee &pcAddr, PilotAddress*,
+ PilotAddress*)
+{
+ FUNCTIONSETUP;
+
+ DEBUGKPILOT<<"Before _savePCAddr, pcAddr.custom="<<pcAddr.custom(KABCSync::appString, KABCSync::idString)<<endl;
+ QString pilotId = pcAddr.custom(KABCSync::appString, KABCSync::idString);
+ long pilotIdL = pilotId.toLong();
+ if(!pilotId.isEmpty())
+ {
+ // because we maintain a mapping between pilotId -> kabc uid, whenever we add
+ // a new relationship, we have to remove any old mapping that would tie a different
+ // pilot id -> this kabc uid
+ QMap < recordid_t, QString>::iterator it;
+ for ( it = addresseeMap.begin(); it != addresseeMap.end(); ++it ) {
+ QString kabcUid = it.data();
+ if (kabcUid == pcAddr.uid()) {
+ addresseeMap.remove(it);
+ break;
+ }
+ }
+
+ // now put the new mapping in
+ addresseeMap.insert(pilotIdL, pcAddr.uid());
+ }
+
+ aBook->insertAddressee(pcAddr);
+
+ abChanged = true;
+ return true;
+}
+
+
+
+
+/*********************************************************************
+ C O P Y R E C O R D S
+ *********************************************************************/
+
+
+
+bool AbbrowserConduit::_equal(const PilotAddress *piAddress, const Addressee &abEntry,
+ enum eqFlagsType flags) const
+{
+ FUNCTIONSETUP;
+
+ // empty records are never equal!
+ if (!piAddress) {
+ DEBUGKPILOT << fname << ": no pilot address passed" << endl;
+ return false;
+ }
+ if (abEntry.isEmpty()) {
+ DEBUGKPILOT << fname << ":abEntry.isEmpty()" << endl;
+ return false;
+ }
+ // Archived records match anything so they won't be copied to the HH again
+ if (flags & eqFlagsFlags)
+ if (isArchived(piAddress) && KABCSync::isArchived(abEntry) ) return true;
+
+ if (flags & eqFlagsName)
+ {
+ if(!_equal(abEntry.familyName(), piAddress->getField(entryLastname)))
+ {
+ DEBUGKPILOT << fname << ": last name not equal" << endl;
+ return false;
+ }
+ if(!_equal(abEntry.givenName(), piAddress->getField(entryFirstname)))
+ {
+ DEBUGKPILOT << fname << ": first name not equal" << endl;
+ return false;
+ }
+ if(!_equal(abEntry.prefix(), piAddress->getField(entryTitle)))
+ {
+ DEBUGKPILOT << fname << ": title/prefix not equal" << endl;
+ return false;
+ }
+ if(!_equal(abEntry.organization(), piAddress->getField(entryCompany)))
+ {
+ DEBUGKPILOT << fname << ": company/organization not equal" << endl;
+ return false;
+ }
+ }
+ if (flags & eqFlagsNote)
+ if(!_equal(abEntry.note(), piAddress->getField(entryNote)))
+ {
+ DEBUGKPILOT << fname << ": note not equal" << endl;
+ return false;
+ }
+
+ if (flags & eqFlagsCategory)
+ {
+ // Check that the name of the category of the HH record
+ // is one matching the PC record.
+ QString addressCategoryLabel = fAddressAppInfo->categoryName(piAddress->category());
+ QString cat = KABCSync::bestMatchedCategoryName(abEntry.categories(),
+ *fAddressAppInfo, piAddress->category());
+ if(!_equal(cat, addressCategoryLabel))
+ {
+ DEBUGKPILOT << fname << ": category not equal" << endl;
+ return false;
+ }
+ }
+
+ if (flags & eqFlagsPhones)
+ {
+ // first, look for missing e-mail addresses on either side
+ QStringList abEmails(abEntry.emails());
+ QStringList piEmails(piAddress->getEmails());
+
+ if (abEmails.count() != piEmails.count())
+ {
+ DEBUGKPILOT << fname << ": email count not equal" << endl;
+ return false;
+ }
+ for (QStringList::Iterator it = abEmails.begin(); it != abEmails.end(); it++) {
+ if (!piEmails.contains(*it))
+ {
+ DEBUGKPILOT << fname << ": pilot e-mail missing" << endl;
+ return false;
+ }
+ }
+ for (QStringList::Iterator it = piEmails.begin(); it != piEmails.end(); it++) {
+ if (!abEmails.contains(*it))
+ {
+ DEBUGKPILOT << fname << ": kabc e-mail missing" << endl;
+ return false;
+ }
+ }
+
+ // now look for differences in phone numbers. Note: we can't just compare one
+ // of each kind of phone number, because there's no guarantee that if the user
+ // has more than one of a given type, we're comparing the correct two.
+
+ PhoneNumber::List abPhones(abEntry.phoneNumbers());
+ PhoneNumber::List piPhones = KABCSync::getPhoneNumbers(*piAddress);
+ // first make sure that all of the pilot phone numbers are in kabc
+ for (PhoneNumber::List::Iterator it = piPhones.begin(); it != piPhones.end(); it++) {
+ PhoneNumber piPhone = *it;
+ bool found=false;
+ for (PhoneNumber::List::Iterator it = abPhones.begin(); it != abPhones.end(); it++) {
+ PhoneNumber abPhone = *it;
+ // see if we have the same number here...
+ // * Note * We used to check for preferred number matching, but
+ // this seems to have broke in kdepim 3.5 and I don't have time to
+ // figure out why, so we won't check to see if preferred number match
+ if ( _equal(piPhone.number(), abPhone.number()) ) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ DEBUGKPILOT << fname << ": not equal because kabc phone not found." << endl;
+ return false;
+ }
+ }
+ // now the other way. *cringe* kabc has the capacity to store way more addresses
+ // than the Pilot, so this might give false positives more than we'd want....
+ for (PhoneNumber::List::Iterator it = abPhones.begin(); it != abPhones.end(); it++) {
+ PhoneNumber abPhone = *it;
+ bool found=false;
+ for (PhoneNumber::List::Iterator it = piPhones.begin(); it != piPhones.end(); it++) {
+ PhoneNumber piPhone = *it;
+ if ( _equal(piPhone.number(), abPhone.number()) ) {
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ {
+ DEBUGKPILOT << fname << ": not equal because pilot phone not found." << endl;
+ return false;
+ }
+ }
+
+ if(!_equal(KABCSync::getFieldForHHOtherPhone(abEntry,fSyncSettings),
+ piAddress->getPhoneField(PilotAddressInfo::eOther)))
+ {
+ DEBUGKPILOT << fname << ": not equal because of other phone field." << endl;
+ return false;
+ }
+ }
+
+ if (flags & eqFlagsAdress)
+ {
+ KABC::Address address = KABCSync::getAddress(abEntry,fSyncSettings);
+ if(!_equal(address.street(), piAddress->getField(entryAddress)))
+ {
+ DEBUGKPILOT << fname << ": address not equal" << endl;
+ return false;
+ }
+ if(!_equal(address.locality(), piAddress->getField(entryCity)))
+ {
+ DEBUGKPILOT << fname << ": city not equal" << endl;
+ return false;
+ }
+ if(!_equal(address.region(), piAddress->getField(entryState)))
+ {
+ DEBUGKPILOT << fname << ": state not equal" << endl;
+ return false;
+ }
+ if(!_equal(address.postalCode(), piAddress->getField(entryZip)))
+ {
+ DEBUGKPILOT << fname << ": zip not equal" << endl;
+ return false;
+ }
+ if(!_equal(address.country(), piAddress->getField(entryCountry)))
+ {
+ DEBUGKPILOT << fname << ": country not equal" << endl;
+ return false;
+ }
+ }
+
+ if (flags & eqFlagsCustom)
+ {
+ unsigned int customIndex = 0;
+ unsigned int hhField = entryCustom1;
+
+ for ( ; customIndex<4; ++customIndex,++hhField )
+ {
+ if (!_equal(KABCSync::getFieldForHHCustom(customIndex, abEntry, fSyncSettings),
+ piAddress->getField(hhField)))
+ {
+ DEBUGKPILOT << fname << ": Custom field " << customIndex
+ << " (HH field " << hhField << ") differs." << endl;
+ return false;
+ }
+ }
+ }
+
+ // if any side is marked archived, but the other is not, the two
+ // are not equal.
+ if ( (flags & eqFlagsFlags) && (isArchived(piAddress) || KABCSync::isArchived(abEntry) ) )
+ {
+ DEBUGKPILOT << fname << ": archived flags don't match" << endl;
+ return false;
+ }
+
+ return true;
+}
+
+
+
+
+
+
+
+
+
+
+/*********************************************************************
+ C O N F L I C T R E S O L U T I O N a n d M E R G I N G
+ *********************************************************************/
+
+
+
+/** smartly merge the given field for the given entry. use the backup record to determine which record has been modified
+ @pc, @backup, @palm ... entries of the according databases
+ @returns string of the merged entries.
+*/
+QString AbbrowserConduit::_smartMergeString(const QString &pc, const QString & backup,
+ const QString & palm, ConflictResolution confRes)
+{
+ FUNCTIONSETUP;
+
+ // if both entries are already the same, no need to do anything
+ if(pc == palm) return pc;
+
+ // If this is a first sync, we don't have a backup record, so
+ if(isFirstSync() || backup.isEmpty()) {
+ if (pc.isEmpty() && palm.isEmpty() ) return QString::null;
+ if(pc.isEmpty()) return palm;
+ if(palm.isEmpty()) return pc;
+ } else {
+ // only one side modified, so return that string, no conflict
+ if(palm == backup) return pc;
+ if(pc == backup) return palm;
+ }
+
+ DEBUGKPILOT<<"pc="<<pc<<", backup="<<backup<<", palm="<<
+ palm<<", ConfRes="<<confRes<<endl;
+ DEBUGKPILOT<<"Use conflict resolution :"<<confRes<<
+ ", PC="<<SyncAction::ePCOverrides<<endl;
+ switch(confRes) {
+ case SyncAction::ePCOverrides: return pc; break;
+ case SyncAction::eHHOverrides: return palm; break;
+ case SyncAction::ePreviousSyncOverrides: return backup; break;
+ default: break;
+ }
+ return QString::null;
+}
+
+
+
+bool AbbrowserConduit::_buildResolutionTable(ResolutionTable*tab, const Addressee &pcAddr,
+ PilotAddress *backupAddr, PilotAddress *palmAddr)
+{
+ FUNCTIONSETUP;
+ if (!tab) return false;
+ tab->setAutoDelete( TRUE );
+ tab->labels[0]=i18n("Item on PC");
+ tab->labels[1]=i18n("Handheld");
+ tab->labels[2]=i18n("Last sync");
+ if (!pcAddr.isEmpty())
+ tab->fExistItems=(eExistItems)(tab->fExistItems|eExistsPC);
+ if (backupAddr)
+ tab->fExistItems=(eExistItems)(tab->fExistItems|eExistsBackup);
+ if (palmAddr)
+ tab->fExistItems=(eExistItems)(tab->fExistItems|eExistsPalm);
+
+#define appendGen(desc, abfield, palmfield) \
+ tab->append(new ResolutionItem(desc, tab->fExistItems, \
+ (!pcAddr.isEmpty())?(abfield):(QString::null), \
+ (palmAddr)?(palmAddr->palmfield):(QString::null), \
+ (backupAddr)?(backupAddr->palmfield):(QString::null) ))
+#define appendAddr(desc, abfield, palmfield) \
+ appendGen(desc, abfield, getField(palmfield))
+#define appendGenPhone(desc, abfield, palmfield) \
+ appendGen(desc, abfield, getPhoneField(PilotAddressInfo::palmfield))
+#define appendPhone(desc, abfield, palmfield) \
+ appendGenPhone(desc, pcAddr.phoneNumber(PhoneNumber::abfield).number(), palmfield)
+
+
+ appendAddr(i18n("Last name"), pcAddr.familyName(), entryLastname);
+ appendAddr(i18n("First name"), pcAddr.givenName(), entryFirstname);
+ appendAddr(i18n("Organization"), pcAddr.organization(), entryCompany);
+ appendAddr(i18n("Title"), pcAddr.prefix(), entryTitle);
+ appendAddr(i18n("Note"), pcAddr.note(), entryNote);
+
+ appendAddr(i18n("Custom 1"), KABCSync::getFieldForHHCustom(0, pcAddr, fSyncSettings), entryCustom1);
+ appendAddr(i18n("Custom 2"), KABCSync::getFieldForHHCustom(1, pcAddr, fSyncSettings), entryCustom2);
+ appendAddr(i18n("Custom 3"), KABCSync::getFieldForHHCustom(2, pcAddr, fSyncSettings), entryCustom3);
+ appendAddr(i18n("Custom 4"), KABCSync::getFieldForHHCustom(3, pcAddr, fSyncSettings), entryCustom4);
+
+ appendPhone(i18n("Work Phone"), Work, eWork);
+ appendPhone(i18n("Home Phone"), Home, eHome);
+ appendPhone(i18n("Mobile Phone"), Cell, eMobile);
+ appendGenPhone(i18n("Fax"), pcAddr.phoneNumber(faxTypeOnPC()).number(), eFax);
+ appendPhone(i18n("Pager"), Pager, ePager);
+ appendGenPhone(i18n("Other"), KABCSync::getFieldForHHOtherPhone(pcAddr,fSyncSettings), eOther);
+ appendGenPhone(i18n("Email"), pcAddr.preferredEmail(), eEmail);
+
+ KABC::Address abAddress = KABCSync::getAddress(pcAddr,fSyncSettings);
+ appendAddr(i18n("Address"), abAddress.street(), entryAddress);
+ appendAddr(i18n("City"), abAddress.locality(), entryCity);
+ appendAddr(i18n("Region"), abAddress.region(), entryState);
+ appendAddr(i18n("Postal code"), abAddress.postalCode(), entryZip);
+ appendAddr(i18n("Country"), abAddress.country(), entryCountry);
+
+ QString palmAddrCategoryLabel;
+ if (palmAddr)
+ {
+ palmAddrCategoryLabel = fAddressAppInfo->categoryName(palmAddr->category());
+ }
+ QString backupAddrCategoryLabel;
+ if (backupAddr)
+ {
+ backupAddrCategoryLabel = fAddressAppInfo->categoryName(backupAddr->category());
+ }
+ int category = palmAddr ? palmAddr->category() : 0;
+ tab->append(new ResolutionItem(
+ i18n("Category"),
+ tab->fExistItems,
+ !pcAddr.isEmpty() ?
+ KABCSync::bestMatchedCategoryName(pcAddr.categories(), *fAddressAppInfo, category) :
+ QString::null,
+ palmAddrCategoryLabel,
+ backupAddrCategoryLabel));
+#undef appendGen
+#undef appendAddr
+#undef appendGenPhone
+#undef appendPhone
+
+ return true;
+}
+
+
+/// This function just sets the phone number of type "type" to "phone"
+static inline void setPhoneNumber(Addressee &abEntry, int type, const QString &nr)
+{
+ PhoneNumber phone = abEntry.phoneNumber(type);
+ phone.setNumber(nr);
+ abEntry.insertPhoneNumber(phone);
+}
+
+
+bool AbbrowserConduit::_applyResolutionTable(ResolutionTable*tab, Addressee &pcAddr,
+ PilotAddress *backupAddr, PilotAddress *palmAddr)
+{
+ FUNCTIONSETUP;
+ if (!tab) return false;
+ if (!palmAddr) {
+ WARNINGKPILOT << "Empty palmAddr after conflict resolution." << endl;
+ return false;
+ }
+
+ ResolutionItem*item=tab->first();
+#define SETGENFIELD(abfield, palmfield) \
+ if (item) {\
+ abfield; \
+ palmAddr->setField(palmfield, item->fResolved); \
+ }\
+ item=tab->next();
+#define SETFIELD(abfield, palmfield) \
+ SETGENFIELD(pcAddr.set##abfield(item->fResolved), palmfield)
+#define SETCUSTOMFIELD(abfield, palmfield) \
+ SETGENFIELD(KABCSync::setFieldFromHHCustom(abfield, pcAddr, item->fResolved, fSyncSettings), palmfield)
+#define SETGENPHONE(abfield, palmfield) \
+ if (item) { \
+ abfield; \
+ palmAddr->setPhoneField(PilotAddressInfo::palmfield, item->fResolved, PilotAddress::Replace); \
+ }\
+ item=tab->next();
+#define SETPHONEFIELD(abfield, palmfield) \
+ SETGENPHONE(setPhoneNumber(pcAddr, PhoneNumber::abfield, item->fResolved), palmfield)
+#define SETADDRESSFIELD(abfield, palmfield) \
+ SETGENFIELD(abAddress.abfield(item->fResolved), palmfield)
+
+ SETFIELD(FamilyName, entryLastname);
+ SETFIELD(GivenName, entryFirstname);
+ SETFIELD(Organization, entryCompany);
+ SETFIELD(Prefix, entryTitle);
+ SETFIELD(Note, entryNote);
+
+ SETCUSTOMFIELD(0, entryCustom1);
+ SETCUSTOMFIELD(1, entryCustom2);
+ SETCUSTOMFIELD(2, entryCustom3);
+ SETCUSTOMFIELD(3, entryCustom4);
+
+ SETPHONEFIELD(Work, eWork);
+ SETPHONEFIELD(Home, eHome);
+ SETPHONEFIELD(Cell, eMobile);
+ SETGENPHONE(setPhoneNumber(pcAddr, faxTypeOnPC(), item->fResolved), eFax);
+ SETPHONEFIELD(Pager, ePager);
+ SETGENPHONE(KABCSync::setFieldFromHHOtherPhone(pcAddr, item->fResolved, fSyncSettings), eOther);
+
+ // TODO: fix email
+ if (item)
+ {
+ palmAddr->setPhoneField(PilotAddressInfo::eEmail, item->fResolved, PilotAddress::Replace);
+ if (backupAddr)
+ {
+ pcAddr.removeEmail(backupAddr->getPhoneField(PilotAddressInfo::eEmail));
+ }
+ pcAddr.removeEmail(palmAddr->getPhoneField(PilotAddressInfo::eEmail));
+ pcAddr.insertEmail(item->fResolved, true);
+ }
+ item=tab->next();
+
+ KABC::Address abAddress = KABCSync::getAddress(pcAddr, fSyncSettings);
+ SETADDRESSFIELD(setStreet, entryAddress);
+ SETADDRESSFIELD(setLocality, entryCity);
+ SETADDRESSFIELD(setRegion, entryState);
+ SETADDRESSFIELD(setPostalCode, entryZip);
+ SETADDRESSFIELD(setCountry, entryCountry);
+ pcAddr.insertAddress(abAddress);
+
+ // TODO: Is this correct?
+ if (item)
+ {
+ palmAddr->setCategory( fAddressAppInfo->findCategory(item->fResolved) );
+ KABCSync::setCategory(pcAddr, item->fResolved);
+ }
+
+
+#undef SETGENFIELD
+#undef SETFIELD
+#undef SETCUSTOMFIELD
+#undef SETGENPHONE
+#undef SETPHONEFIELD
+#undef SETADDRESSFIELD
+
+ return true;
+}
+
+
+
+bool AbbrowserConduit::_smartMergeTable(ResolutionTable*tab)
+{
+ FUNCTIONSETUP;
+ if (!tab) return false;
+ bool noconflict=true;
+ ResolutionItem*item;
+ for ( item = tab->first(); item; item = tab->next() )
+ {
+ // try to merge the three strings
+ item->fResolved=_smartMergeString(item->fEntries[0],
+ item->fEntries[2], item->fEntries[1], getConflictResolution());
+ // if a conflict occurred, set the default to something sensitive:
+ if (item->fResolved.isNull() && !(item->fEntries[0].isEmpty() &&
+ item->fEntries[1].isEmpty() && item->fEntries[2].isEmpty() ) )
+ {
+ item->fResolved=item->fEntries[0];
+ noconflict=false;
+ }
+ if (item->fResolved.isNull()) item->fResolved=item->fEntries[1];
+ if (item->fResolved.isNull()) item->fResolved=item->fEntries[2];
+ }
+ return noconflict;
+}
+
+
+
+/** Merge the palm and the pc entries with the additional information of
+ * the backup.
+ * return value: no meaning yet
+ */
+bool AbbrowserConduit::_smartMergeAddressee(Addressee &pcAddr,
+ PilotAddress *backupAddr, PilotAddress *palmAddr)
+{
+ FUNCTIONSETUP;
+
+ // Merge them, then look which records have to be written to device or abook
+ int res = SyncAction::eAskUser;
+ bool result=true;
+ ResolutionTable tab;
+
+ result &= _buildResolutionTable(&tab, pcAddr, backupAddr, palmAddr);
+ // Now attempt a smart merge. If that fails, let conflict resolution do the job
+ bool mergeOk=_smartMergeTable(&tab);
+
+ if (!mergeOk)
+ {
+ QString dlgText;
+ if (!palmAddr)
+ {
+ dlgText=i18n("The following address entry was changed, but does no longer exist on the handheld. Please resolve this conflict:");
+ }
+ else if (pcAddr.isEmpty())
+ {
+ dlgText=i18n("The following address entry was changed, but does no longer exist on the PC. Please resolve this conflict:");
+ }
+ else
+ {
+ dlgText=i18n("The following address entry was changed on the handheld as well as on the PC side. The changes could not be merged automatically, so please resolve the conflict yourself:");
+ }
+ ResolutionDlg*resdlg=new ResolutionDlg(0L, fHandle, i18n("Address conflict"), dlgText, &tab);
+ resdlg->exec();
+ KPILOT_DELETE(resdlg);
+ }
+ res=tab.fResolution;
+
+ // Disallow some resolution under certain conditions, fix wrong values:
+ switch (res) {
+ case SyncAction::eHHOverrides:
+ if (!palmAddr) res=SyncAction::eDelete;
+ break;
+ case SyncAction::ePCOverrides:
+ if (pcAddr.isEmpty()) res=SyncAction::eDelete;
+ break;
+ case SyncAction::ePreviousSyncOverrides:
+ if (!backupAddr) res=SyncAction::eDoNothing;
+ break;
+ }
+
+ PilotAddress*pAddr=palmAddr;
+ bool pAddrCreated=false;
+ // Now that we have done a possible conflict resolution, apply the changes
+ switch (res) {
+ case SyncAction::eDuplicate:
+ // Set the Palm ID to 0 so we don't overwrite the existing record.
+ pcAddr.removeCustom(KABCSync::appString, KABCSync::idString);
+ result &= _copyToHH(pcAddr, 0L, 0L);
+ {
+ Addressee pcadr;
+ result &= _copyToPC(pcadr, backupAddr, palmAddr);
+ }
+ break;
+ case SyncAction::eDoNothing:
+ break;
+ case SyncAction::eHHOverrides:
+ result &= _copyToPC(pcAddr, backupAddr, palmAddr);
+ break;
+ case SyncAction::ePCOverrides:
+ result &= _copyToHH(pcAddr, backupAddr, pAddr);
+ break;
+ case SyncAction::ePreviousSyncOverrides:
+ KABCSync::copy(pcAddr, *backupAddr, *fAddressAppInfo, fSyncSettings);
+ if (palmAddr && backupAddr) *palmAddr=*backupAddr;
+ result &= _savePalmAddr(backupAddr, pcAddr);
+ result &= _savePCAddr(pcAddr, backupAddr, backupAddr);
+ break;
+ case SyncAction::eDelete:
+ result &= _deleteAddressee(pcAddr, backupAddr, palmAddr);
+ break;
+ case SyncAction::eAskUser:
+ default:
+ if (!pAddr)
+ {
+ pAddr=new PilotAddress();
+ pAddrCreated=true;
+ }
+ result &= _applyResolutionTable(&tab, pcAddr, backupAddr, pAddr);
+showAddresses(pcAddr, backupAddr, pAddr);
+ // savePalmAddr sets the RecordID custom field already
+ result &= _savePalmAddr(pAddr, pcAddr);
+ result &= _savePCAddr(pcAddr, backupAddr, pAddr);
+ if (pAddrCreated) KPILOT_DELETE(pAddr);
+ break;
+ }
+
+ return result;
+}
+
+
+
+// TODO: right now entries are equal if both first/last name and organization are
+// equal. This rules out two entries for the same person(e.g. real home and weekend home)
+// or two persons with the same name where you don't know the organization.!!!
+Addressee AbbrowserConduit::_findMatch(const PilotAddress & pilotAddress) const
+{
+ FUNCTIONSETUP;
+ // TODO: also search with the pilotID
+ // first, use the pilotID to UID map to find the appropriate record
+ if( !isFirstSync() && (pilotAddress.id() > 0) )
+ {
+ QString id(addresseeMap[pilotAddress.id()]);
+ DEBUGKPILOT << fname << ": PilotRecord has id " << pilotAddress.id() << ", mapped to " << id << endl;
+ if(!id.isEmpty())
+ {
+ Addressee res(aBook->findByUid(id));
+ if(!res.isEmpty()) return res;
+ DEBUGKPILOT << fname << ": PilotRecord has id " << pilotAddress.id() << ", but could not be found in the addressbook" << endl;
+ }
+ }
+
+ for(AddressBook::Iterator iter = aBook->begin(); iter != aBook->end(); ++iter)
+ {
+ Addressee abEntry = *iter;
+ QString recID(abEntry.custom(KABCSync::appString, KABCSync::idString));
+ bool ok;
+ if (!recID.isEmpty() )
+ {
+ recordid_t rid = recID.toLong(&ok);
+ if (ok && rid)
+ {
+ if (rid==pilotAddress.id()) return abEntry;// yes, we found it
+ // skip this addressee, as it can an other corresponding address on the handheld
+ if (allIds.contains(rid)) continue;
+ }
+ }
+
+ if (_equal(&pilotAddress, abEntry, eqFlagsAlmostAll))
+ {
+ return abEntry;
+ }
+ }
+ DEBUGKPILOT << fname << ": Could not find any addressbook enty matching " << pilotAddress.getField(entryLastname) << endl;
+ return Addressee();
+}
+
+void AbbrowserConduit::slotTestRecord()
+{
+ FUNCTIONSETUP;
+
+ // Get a record and interpret it as an address.
+ PilotRecord *r = fDatabase->readRecordByIndex( pilotindex );
+ if (!r)
+ {
+ delayDone();
+ return;
+ }
+ PilotAddress a(r);
+ KPILOT_DELETE(r);
+
+ // Process this record.
+ showPilotAddress(&a);
+
+ // Schedule more work.
+ ++pilotindex;
+ QTimer::singleShot(0, this, SLOT(slotTestRecord()));
+}
diff --git a/kpilot/conduits/abbrowserconduit/abbrowser-conduit.h b/kpilot/conduits/abbrowserconduit/abbrowser-conduit.h
new file mode 100644
index 000000000..484f61292
--- /dev/null
+++ b/kpilot/conduits/abbrowserconduit/abbrowser-conduit.h
@@ -0,0 +1,222 @@
+#ifndef _ABBROWSER_CONDUIT_H
+#define _ABBROWSER_CONDUIT_H
+/* abbrowser-conduit.h KPilot
+**
+** Copyright (C) 2000,2001 by Dan Pilone
+** Copyright (C) 2000 Gregory Stern
+** Copyright (C) 2002-2003 by Reinhold Kainhofer
+**
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+
+#include <kabc/addressbook.h>
+
+#include <pilotAddress.h>
+#include <plugin.h>
+
+#include "kabcRecord.h"
+
+
+class ResolutionTable;
+namespace KABC
+{
+class Addressee;
+class Address;
+class PhoneNumber;
+class Ticket;
+}
+
+using namespace KABC;
+
+typedef QValueList<recordid_t> RecordIDList;
+
+class AbbrowserConduit : public ConduitAction
+{
+Q_OBJECT
+public:
+ AbbrowserConduit(KPilotLink *o,const char *n = 0L,
+ const QStringList &a = QStringList() );
+ virtual ~AbbrowserConduit();
+
+/*********************************************************************
+ S Y N C S T R U C T U R E
+ *********************************************************************/
+ virtual bool exec();
+protected slots:
+ void slotPalmRecToPC();
+ void slotPCRecToPalm();
+ void slotDeletedRecord();
+ void slotDeleteUnsyncedPCRecords();
+ void slotDeleteUnsyncedHHRecords();
+ void slotCleanup();
+
+ void slotTestRecord();
+
+private:
+
+ /********************************************************/
+ /* Handle the configuration */
+ /********************************************************/
+
+ /* Read the global KPilot config file for settings
+ * particular to the AbbrowserConduit conduit. */
+ void readConfig();
+
+ void showPilotAddress(const PilotAddress *pilotAddress);
+ void showAddresses(
+ const Addressee &pcAddr,
+ const PilotAddress *backupAddr,
+ const PilotAddress *palmAddr);
+
+
+ /********************************************************/
+ /* Loading and saving the addressbook and database */
+ /********************************************************/
+
+
+ /* Given a list of contacts, creates the pilot id to contact key map
+ * and a list of new contacts in O(n) time (single pass) */
+ void _mapContactsToPilot( QMap < recordid_t, QString> &idContactMap);
+ /* Do the preperations before doSync or doBackup.
+ * Load contacts, set the pilot */
+ bool _prepare();
+ /* Load the contacts from the addressbook.
+ * @return true if successful, false if not */
+ bool _loadAddressBook();
+ /* Save the contacts back to the addressbook.
+ * @return true if successful, false if not */
+ bool _saveAddressBook();
+ void _getAppInfo();
+ void _setAppInfo();
+
+ void _cleanupAddressBookPointer();
+
+
+
+/*********************************************************************
+ G E N E R A L S Y N C F U N C T I O N
+ These functions modify the Handheld and the addressbook
+ *********************************************************************/
+ bool syncAddressee(Addressee &pcAddr, PilotAddress*backupAddr,
+ PilotAddress*palmAddr);
+ bool _copyToHH(Addressee &pcAddr, PilotAddress*backupAddr,
+ PilotAddress*palmAddr);
+ bool _copyToPC(Addressee &pcAddr, PilotAddress*backupAddr,
+ PilotAddress*palmAddr);
+ bool _writeBackup(PilotAddress *backup);
+ bool _deleteAddressee(Addressee &pcAddr, PilotAddress*backupAddr,
+ PilotAddress*palmAddr);
+
+
+/*********************************************************************
+ l o w - l e v e l f u n c t i o n s f o r
+ adding / removing palm/pc records
+ *********************************************************************/
+ bool _savePalmAddr(PilotAddress *palmAddr, Addressee &pcAddr);
+ bool _savePCAddr(Addressee &pcAddr, PilotAddress*backupAddr,
+ PilotAddress*palmAddr);
+
+
+/*********************************************************************
+ C O P Y R E C O R D S
+ *********************************************************************/
+ inline bool _equal(const QString & str1, const QString & str2) const
+ {
+ return (str1.isEmpty() && str2.isEmpty()) || (str1 == str2);
+ } ;
+ typedef enum eqFlagsType
+ {
+ eqFlagsName=0x1,
+ eqFlagsAdress=0x2,
+ eqFlagsPhones=0x4,
+ eqFlagsNote=0x8,
+ eqFlagsCategory=0x10,
+ eqFlagsFlags=0x20,
+ eqFlagsCustom=0x40,
+ eqFlagsAll=0xFFFF,
+ eqFlagsAlmostAll=eqFlagsName|eqFlagsAdress|eqFlagsPhones|eqFlagsNote|eqFlagsCustom
+ };
+ bool _equal(const PilotAddress *piAddress, const Addressee &abEntry,
+ enum eqFlagsType flags=eqFlagsAll) const;
+
+/*********************************************************************
+ C O N F L I C T R E S O L U T I O N a n d M E R G I N G
+ *********************************************************************/
+ /** smartly merge the given field for the given entry. use the
+ * backup record to determine which record has been modified
+ * @pc, @backup, @palm ... entries of the according databases
+ * @returns string of the merged entries.
+ */
+ QString _smartMergeString(const QString &pc, const QString & backup,
+ const QString & palm, ConflictResolution confRes);
+ bool _buildResolutionTable(ResolutionTable*tab, const Addressee &pcAddr,
+ PilotAddress *backupAddr, PilotAddress *palmAddr);
+ bool _applyResolutionTable(ResolutionTable*tab, Addressee &pcAddr,
+ PilotAddress *backupAddr, PilotAddress *palmAddr);
+ bool _smartMergeTable(ResolutionTable*tab);
+ /** Merge the palm and the pc entries with the additional
+ * information of the backup record. Calls _smartMerge
+ * which does the actual syncing of the data structures.
+ * According to the return value of _smartMerge, this function
+ * writes the data back to the palm/pc.
+ * return value: no meaning yet
+ */
+ bool _smartMergeAddressee(Addressee &pcAddr, PilotAddress *backupAddr,
+ PilotAddress *palmAddr);
+ Addressee _findMatch(const PilotAddress & pilotAddress) const;
+
+
+/********************************************************/
+/* D A T A M E M B E R S , S E T T I N G S */
+/********************************************************/
+
+ AddressBook* aBook;
+
+ PilotAddressInfo *fAddressAppInfo;
+
+ KABCSync::Settings fSyncSettings;
+
+ int pilotindex;
+ bool abChanged;
+ /** addresseeMap maps record ids to IDs of Addressees. This is used to speed up searching the local addressbook */
+ QMap < recordid_t, QString> addresseeMap;
+ RecordIDList syncedIds, allIds;
+ QString fABookFile;
+ AddressBook::Iterator abiter;
+ /** For a local file resource, we need to obtain a saveTicket
+ * when opening the abook, just in case we want to modify it
+ * at all.
+ */
+ Ticket *fTicket;
+ bool fCreatedBook;
+
+ /** if we add a resource from the addressbook, track it to remove it
+ * later...
+ */
+ KABC::Resource *fBookResource;
+
+
+} ;
+
+#endif
diff --git a/kpilot/conduits/abbrowserconduit/abbrowser-factory.cc b/kpilot/conduits/abbrowserconduit/abbrowser-factory.cc
new file mode 100644
index 000000000..9a8450840
--- /dev/null
+++ b/kpilot/conduits/abbrowserconduit/abbrowser-factory.cc
@@ -0,0 +1,45 @@
+/* KPilot
+**
+** Copyright (C) 2001 by Dan Pilone
+** Copyright (C) 2002-2003 Reinhold Kainhofer
+**
+** This file defines the factory for the abbrowser-conduit plugin.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include "options.h"
+
+#include "pluginfactory.h"
+
+#include "abbrowser-conduit.h"
+#include "abbrowser-setup.h"
+
+extern "C"
+{
+
+void *init_conduit_address()
+{
+ return new ConduitFactory<AbbrowserWidgetSetup,AbbrowserConduit>(0,"abbrowserconduit");
+}
+
+}
diff --git a/kpilot/conduits/abbrowserconduit/abbrowser-factory.h b/kpilot/conduits/abbrowserconduit/abbrowser-factory.h
new file mode 100644
index 000000000..bbf573c7f
--- /dev/null
+++ b/kpilot/conduits/abbrowserconduit/abbrowser-factory.h
@@ -0,0 +1,40 @@
+#ifndef _ABBROWSER_FACTORY_H
+#define _ABBROWSER_FACTORY_H
+/* abbrowser-factory.h KPilot
+**
+** Copyright (C) 2001 by Dan Pilone
+** Copyright (C) 2002-2003 Reinhold Kainhofer
+**
+** This file defines the factory for the abbrowser-conduit plugin.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+extern "C"
+{
+
+void *init_conduit_address();
+
+}
+
+#endif
+
diff --git a/kpilot/conduits/abbrowserconduit/abbrowser-setup.cc b/kpilot/conduits/abbrowserconduit/abbrowser-setup.cc
new file mode 100644
index 000000000..4a2aa4215
--- /dev/null
+++ b/kpilot/conduits/abbrowserconduit/abbrowser-setup.cc
@@ -0,0 +1,195 @@
+/* KPilot
+**
+** Copyright (C) 2001 by Dan Pilone
+** Copyright (C) 2002-2003 Reinhold Kainhofer
+**
+** This file defines the setup dialog for the abbrowser-conduit plugin.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include "options.h"
+
+#include <qcheckbox.h>
+#include <qcombobox.h>
+#include <qbuttongroup.h>
+
+#include <kurlrequester.h>
+#include <kaboutdata.h>
+
+#include "kaddressbookConduit.h"
+#include "abbrowser-setup.h"
+#include "abbrowserSettings.h"
+
+
+
+static KAboutData *createAbout()
+{
+ KAboutData *fAbout = new KAboutData("abbrowserconduit",
+ I18N_NOOP("Abbrowser Conduit for KPilot"),
+ KPILOT_VERSION,
+ I18N_NOOP("Configures the Abbrowser Conduit for KPilot"),
+ KAboutData::License_GPL,
+ "(C) 2001, Dan Pilone\n(C) 2002-2003, Reinhold Kainhofer");
+ fAbout->addAuthor("Greg Stern",
+ I18N_NOOP("Primary Author"));
+ fAbout->addAuthor("Adriaan de Groot",
+ I18N_NOOP("Maintainer"),
+ "groot@kde.org",
+ "http://www.cs.kun.nl/~adridg/kpilot");
+ fAbout->addAuthor("Reinhold Kainhofer", I18N_NOOP("Maintainer"),
+ "reinhold@kainhofer.com", "http://reinhold.kainhofer.com");
+ fAbout->addCredit("David Bishop", I18N_NOOP("UI"));
+ return fAbout;
+}
+
+AbbrowserWidgetSetup::AbbrowserWidgetSetup(QWidget *w, const char *n) :
+ ConduitConfigBase(w,n),
+ fConfigWidget(new AbbrowserWidget(w))
+{
+ FUNCTIONSETUP;
+
+ fConduitName=i18n("Addressbook");
+ fAbout = createAbout();
+ ConduitConfigBase::addAboutPage(fConfigWidget->tabWidget,fAbout);
+ fWidget=fConfigWidget;
+ fConfigWidget->fAbookFile->setMode(KFile::File);
+#define CM(a,b) connect(fConfigWidget->a,b,this,SLOT(modified()));
+ CM(fSyncDestination,SIGNAL(clicked(int)));
+ CM(fAbookFile,SIGNAL(textChanged(const QString &)));
+ CM(fArchive,SIGNAL(toggled(bool)));
+ CM(fConflictResolution,SIGNAL(activated(int)));
+ CM(fOtherPhone,SIGNAL(activated(int)));
+ CM(fAddress,SIGNAL(activated(int)));
+ CM(fFax,SIGNAL(activated(int)));
+ CM(fCustom0,SIGNAL(activated(int)));
+ CM(fCustom1,SIGNAL(activated(int)));
+ CM(fCustom2,SIGNAL(activated(int)));
+ CM(fCustom3,SIGNAL(activated(int)));
+ CM(fCustomDate, SIGNAL(activated(int)));
+ CM(fCustomDate, SIGNAL(textChanged(const QString&)));
+#undef CM
+}
+
+AbbrowserWidgetSetup::~AbbrowserWidgetSetup()
+{
+ FUNCTIONSETUP;
+}
+
+/* virtual */ void AbbrowserWidgetSetup::commit()
+{
+ FUNCTIONSETUP;
+
+ QButtonGroup*grp=fConfigWidget->fSyncDestination;
+ AbbrowserSettings::setAddressbookType(grp->id(grp->selected()));
+ AbbrowserSettings::setFileName(fConfigWidget->fAbookFile->url());
+ AbbrowserSettings::setArchiveDeleted(fConfigWidget->fArchive->isChecked());
+
+ // Conflicts page
+ AbbrowserSettings::setConflictResolution(
+ fConfigWidget->fConflictResolution->currentItem()+SyncAction::eCROffset);
+
+ // Fields page
+ AbbrowserSettings::setPilotOther(fConfigWidget->fOtherPhone->currentItem());
+ AbbrowserSettings::setPilotStreet(fConfigWidget->fAddress->currentItem());
+ AbbrowserSettings::setPilotFax(fConfigWidget->fFax->currentItem());
+
+ // Custom fields page
+ AbbrowserSettings::setCustom0(fConfigWidget->fCustom0->currentItem());
+ AbbrowserSettings::setCustom1(fConfigWidget->fCustom1->currentItem());
+ AbbrowserSettings::setCustom2(fConfigWidget->fCustom2->currentItem());
+ AbbrowserSettings::setCustom3(fConfigWidget->fCustom3->currentItem());
+#ifdef DEBUG
+ DEBUGKPILOT <<fname<<
+ "Custom0: "<<fConfigWidget->fCustom0->currentItem()<<" "<<
+ "Custom1: "<<fConfigWidget->fCustom1->currentItem()<<" "<<
+ "Custom2: "<<fConfigWidget->fCustom2->currentItem()<<" "<<
+ "Custom3: "<<fConfigWidget->fCustom3->currentItem()<<" "
+ << " eCustom[0]=" << AbbrowserSettings::custom0()<<" "
+ << " eCustom[1]=" << AbbrowserSettings::custom1()<<" "
+ << " eCustom[2]=" << AbbrowserSettings::custom2()<<" "
+ << " eCustom[3]=" << AbbrowserSettings::custom3()<<" "<<
+ endl;
+#endif
+ int fmtindex=fConfigWidget->fCustomDate->currentItem();
+ AbbrowserSettings::setCustomDateFormat(
+ (fmtindex==0)?(QString::null):fConfigWidget->fCustomDate->currentText() );
+
+ AbbrowserSettings::self()->writeConfig();
+ unmodified();
+}
+
+/* virtual */ void AbbrowserWidgetSetup::load()
+{
+ FUNCTIONSETUP;
+ AbbrowserSettings::self()->readConfig();
+
+#ifdef DEBUG
+ DEBUGKPILOT << fname
+ << ": Settings "
+ << " fPilotStreetHome=" << AbbrowserSettings::pilotStreet()
+ << " fPilotFaxHome=" << AbbrowserSettings::pilotFax()
+ << " fArchive=" << AbbrowserSettings::archiveDeleted()
+ << " eCustom[0]=" << AbbrowserSettings::custom0()
+ << " eCustom[1]=" << AbbrowserSettings::custom1()
+ << " eCustom[2]=" << AbbrowserSettings::custom2()
+ << " eCustom[3]=" << AbbrowserSettings::custom3()
+ << endl;
+#endif
+
+ // General page
+ fConfigWidget->fSyncDestination->setButton(AbbrowserSettings::addressbookType());
+ fConfigWidget->fAbookFile->setURL(AbbrowserSettings::fileName());
+ fConfigWidget->fArchive->setChecked(AbbrowserSettings::archiveDeleted());
+
+ // Conflicts page
+ fConfigWidget->fConflictResolution->setCurrentItem(
+ AbbrowserSettings::conflictResolution() - SyncAction::eCROffset );
+
+ // Fields page
+ fConfigWidget->fOtherPhone->setCurrentItem(AbbrowserSettings::pilotOther());
+ fConfigWidget->fAddress->setCurrentItem(AbbrowserSettings::pilotStreet());
+ fConfigWidget->fFax->setCurrentItem(AbbrowserSettings::pilotFax());
+
+ // Custom fields page
+ fConfigWidget->fCustom0->setCurrentItem(AbbrowserSettings::custom0());
+ fConfigWidget->fCustom1->setCurrentItem(AbbrowserSettings::custom1());
+ fConfigWidget->fCustom2->setCurrentItem(AbbrowserSettings::custom2());
+ fConfigWidget->fCustom3->setCurrentItem(AbbrowserSettings::custom3());
+ QString datefmt=AbbrowserSettings::customDateFormat();
+ if (datefmt.isEmpty())
+ {
+ fConfigWidget->fCustomDate->setCurrentItem(0);
+ }
+ else
+ {
+ fConfigWidget->fCustomDate->setCurrentText(datefmt);
+ }
+
+ unmodified();
+}
+
+/* static */ ConduitConfigBase *AbbrowserWidgetSetup::create(QWidget *w, const char *n)
+{
+ return new AbbrowserWidgetSetup(w,n);
+}
+
diff --git a/kpilot/conduits/abbrowserconduit/abbrowser-setup.h b/kpilot/conduits/abbrowserconduit/abbrowser-setup.h
new file mode 100644
index 000000000..71981dc09
--- /dev/null
+++ b/kpilot/conduits/abbrowserconduit/abbrowser-setup.h
@@ -0,0 +1,52 @@
+#ifndef _ABBROWSER_ABBROWSER_SETUP_H
+#define _ABBROWSER_ABBROWSER_SETUP_H
+/* knotes-setup.h KPilot
+**
+** Copyright (C) 2001 by Dan Pilone
+** Copyright (C) 2002-2003 Reinhold Kainhofer
+**
+** This file defines the widget and behavior for the config dialog
+** of the KNotes conduit.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include "plugin.h"
+
+class AbbrowserWidget;
+class KAboutData;
+
+class AbbrowserWidgetSetup : public ConduitConfigBase
+{
+public:
+ AbbrowserWidgetSetup(QWidget *,const char *);
+ virtual ~AbbrowserWidgetSetup();
+ virtual void load();
+ virtual void commit();
+ static ConduitConfigBase *create(QWidget *,const char *);
+private:
+ AbbrowserWidget *fConfigWidget;
+ KAboutData *fAbout;
+} ;
+
+#endif
+
diff --git a/kpilot/conduits/abbrowserconduit/abbrowserSettings.kcfgc b/kpilot/conduits/abbrowserconduit/abbrowserSettings.kcfgc
new file mode 100644
index 000000000..f6ea2097f
--- /dev/null
+++ b/kpilot/conduits/abbrowserconduit/abbrowserSettings.kcfgc
@@ -0,0 +1,7 @@
+File=abbrowserconduit.kcfg
+ClassName=AbbrowserSettings
+Singleton=true
+ItemAccessors=true
+Mutators=true
+GlobalEnums=true
+SetUserTexts=true
diff --git a/kpilot/conduits/abbrowserconduit/abbrowser_conduit.desktop b/kpilot/conduits/abbrowserconduit/abbrowser_conduit.desktop
new file mode 100644
index 000000000..f25f458f2
--- /dev/null
+++ b/kpilot/conduits/abbrowserconduit/abbrowser_conduit.desktop
@@ -0,0 +1,116 @@
+[Desktop Entry]
+Type=Service
+Comment=This conduit syncs the handheld addressbook with KDE's addressbook.
+Comment[af]=Hierdie pad sinkroniseer die draagbare toestel adresboek met KDE se adresboek.
+Comment[bg]=Ð¡Ð¸Ð½Ñ…Ñ€Ð¾Ð½Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð½Ð° адреÑника на KDE Ñ Ð¼Ð¾Ð±Ð¸Ð»Ð½Ð¸ уÑтройÑтва
+Comment[bs]=Ovaj conduit sinhronizuje adresar ruÄnog raÄunara sa KDEovim adresarom.
+Comment[ca]=Aquest conducte sincronitza la llibreta d'adreces de la vostra agenda electrònica amb la llibreta d'adreces de KDE.
+Comment[cs]=Toto propojení synchronizuje vašeho Pilota Knihou adres
+Comment[cy]=Mae'r cwndid yma yn cydamseru llyfr cyfeiriadau'r llawiadur efo llyfr cyfeiriadau KDE.
+Comment[da]=Denne kanal synkroniserer din håndholdte med KDE's adressebog.
+Comment[de]=Abgleich der Adressbücher von Taschencomputer und KDE.
+Comment[el]=Αυτός ο σÏνδεσμος συγχÏονίζει το βιβλίο διευθÏνσεων του υπολογιστή παλάμης με το βιβλίο διευθÏνσεων του KDE.
+Comment[eo]=Tiu kanalo sinkronigas vian poÅkomputil-adreslibron kun la KDE-aadreslibro.
+Comment[es]=Este conducto sincroniza la libreta de direcciones de su agenda electrónica con la de KDE
+Comment[et]=See kanal sünkroniseerib pihuarvuti ja KDE aadressiraamatu.
+Comment[eu]=Kanal honek agenda-elektronikoaren helbide-liburua KDE-ren helbide-liburuarekin sinkronizatzen du.
+Comment[fa]=این لوله، کتاب نشانی دستی را با کتاب نشانی KDE همگام می‌سازد.
+Comment[fi]=Tämä yhdyskäytävä synkronoi taskutietokoneen KDE:n osoitekirjan kanssa
+Comment[fr]=Ce canal synchronise le carnet d'adresses du périphérique avec celui de KDE.
+Comment[fy]=Dit conduit syngronisearret jo handheld mei KDE's adresboek.
+Comment[gl]=Este conducto sincroniza o caderno de enderezos do seu aparello portátil co caderno de enderezos de KDE.
+Comment[hi]=यह कनà¥à¤¡à¥à¤¯à¥‚इट हैंडहेलà¥à¤¡ पता-पà¥à¤¸à¥à¤¤à¤¿à¤•à¤¾ को केडीई के पता-पà¥à¤¸à¥à¤¤à¤¿à¤•à¤¾ से सिंक करती है.
+Comment[hu]=Ezzel a csatolóval egy kéziszámítógép és a KDE címjegyzéke között lehet szinkronizálást végezni.
+Comment[is]=Þessi rás samstillir póstfangaskrár KDE og lófatölvunnar
+Comment[it]=Questo condotto sincronizza il tuo palmare con la rubrica indirizzi di KDE
+Comment[ja]=ã“ã®ã‚³ãƒ³ã‚¸ãƒƒãƒˆã¯ãƒãƒ³ãƒ‰ãƒ˜ãƒ«ãƒ‰ã®ã‚¢ãƒ‰ãƒ¬ã‚¹å¸³ã‚’KDEã®ã‚¢ãƒ‰ãƒ¬ã‚¹å¸³ã¨åŒæœŸã•ã›ã¾ã™ã€‚
+Comment[ka]=ეს áƒáƒ áƒ®áƒ˜ KDE-ს წიგნáƒáƒ™áƒ˜áƒ¡ სინქრáƒáƒœáƒ˜áƒ–áƒáƒªáƒ˜áƒáƒ¡ áƒáƒ®áƒ“ენს პáƒáƒ áƒ¢áƒáƒ¢áƒ˜áƒ£áƒš წიგნáƒáƒ™áƒ—áƒáƒœ.
+Comment[kk]=Қалта құрылғыдағы адреÑтік кітапшамен KDE-нің адреÑтік кітапшаларды қадамдаÑтыру арнаÑÑ‹.
+Comment[km]=បំពង់​នáŸáŸ‡â€‹áž¢áž¶áž…​ឲ្យ​សៀវភៅ​អាសយដ្ឋាន​របស់​ឧបករណáŸâ€‹áž™áž½ážšážŠáŸƒ ធ្វើ​សមកាលកម្ម​ជាមួយ​នឹង​សៀវភៅ​អាសយដ្ឋាន​របស់ KDE
+Comment[lt]=Šis kanalas sinchronizuoja nešiojamą adresų knygelę su KDE adresų knygele.
+Comment[mk]=Овој канал ги Ñинхронизира адреÑарите од рачниот уред и од KDE.
+Comment[ms]=Saluran ini mensegerakkan buku alamat komputer telapak dengan buku alamat KDE.
+Comment[nb]=Denne kanalen synkroniserer Pilotens adressebok med KDEs adressebok.
+Comment[nds]=Synkroniseert de Adressböker vun Handreekners un KDE.
+Comment[ne]=यो कनà¥à¤¡à¥à¤¯à¥à¤Ÿà¤²à¥‡ केडीई को ठेगाना पà¥à¤¸à¥à¤¤à¤•à¤®à¤¾ हà¥à¤¯à¤¾à¤¨à¥à¤¡à¤² गरिà¤à¤•à¤¾ ठेगाना पà¥à¤¸à¥à¤¤à¤¿à¤•à¤¾ सिनà¥à¤• गरà¥à¤¦à¤› ।
+Comment[nl]=Dit conduit synchroniseert uw handheld met KDE's adresboek.
+Comment[nn]=Denne koplinga synkroniserer den handheldte adresseboka med med KDE-adresseboka.
+Comment[pl]=Ten łącznik synchronizuje książkę adresową palmtopa z książką adresową KDE.
+Comment[pt]=Esta conduta sincroniza o livro de endereços ou agenda do seu dispositivo com a agenda do KDE.
+Comment[pt_BR]=Este conduíte sincroniza o livro de endereços do handheld com o livro de endereços do KDE.
+Comment[ru]=Канал Ñинхронизации адреÑных книг КПК и KDE.
+Comment[sk]=Táto spojka synchronizuje adresár vášho prenosného zariadenia s adresárom KDE.
+Comment[sl]=Ta veznik usklajuje adresar v roÄnem raÄunalniku z adresarjem v KDE.
+Comment[sr]=Овај провод Ñинхронизује адреÑар ручног рачунара Ñа KDE-овим адреÑаром
+Comment[sr@Latn]=Ovaj provod sinhronizuje adresar ruÄnog raÄunara sa KDE-ovim adresarom
+Comment[sv]=Den här kanalen synkroniserar handdatorns adressbok med KDE:s adressbok.
+Comment[ta]=இநà¯à®¤ கà¯à®´à®¾à®¯à¯ கையில௠உளà¯à®³ à®®à¯à®•à®µà®°à®¿à®ªà¯à®ªà¯à®¤à¯à®¤à®•à®¤à¯à®¤à¯ˆ கேடிஇயின௠மà¯à®•à®µà®°à®¿à®ªà¯à®ªà¯à®¤à¯à®¤à®•à®¤à¯à®¤à¯‹à®Ÿà¯ ஒதà¯à®¤à®¿à®šà¯ˆà®•à¯à®•à®¿à®±à®¤à¯
+Comment[tg]=Канали ÑинхронизатÑиÑи китоби адреÑии Pilot ва KDE.
+Comment[tr]=Bu bileşen el bilgisayarı adres defteri ile KDE'ninkini birleştirir.
+Comment[uk]=Цей акведук Ñинхронізує адреÑну книгу кишенькового приÑтрою з адреÑною книгою KDE.
+Comment[zh_CN]=此管é“会将您的手æŒè®¾å¤‡ä¸Ž KDE 的地å€ç°¿åŒæ­¥ã€‚
+Comment[zh_TW]=此軟體讓您把 KDE 通訊錄與手邊通訊錄åŒæ­¥ã€‚
+Name=Addressbook
+Name[af]=Adresboek
+Name[ar]=دÙتر العناوين
+Name[az]=Ünvan Dəftəri
+Name[be]=ÐдраÑÐ½Ð°Ñ ÐºÐ½Ñ–Ð³Ð°
+Name[bg]=ÐдреÑник
+Name[br]=Karned chomlec'hioù
+Name[bs]=Adresar
+Name[ca]=Llibreta d'adreces
+Name[cs]=Kniha adres
+Name[cy]=Llyfr Cyfeiriadau
+Name[da]=Adressebog
+Name[de]=Adressbuch
+Name[el]=Βιβλίο διευθÏνσεων
+Name[eo]=Adresaro
+Name[es]=Libreta de direcciones
+Name[et]=Aadressiraamat
+Name[eu]=Helbide-liburua
+Name[fa]=کتاب نشانی
+Name[fi]=Osoitekirja
+Name[fr]=Carnet d'adresses
+Name[fy]=Adresboek
+Name[ga]=Leabhar Seoltaí
+Name[gl]=Libro de enderezos
+Name[hi]=पता-पà¥à¤¸à¥à¤¤à¤¿à¤•à¤¾
+Name[hr]=Adresar
+Name[hu]=Címjegyzék
+Name[id]=Buku alamat
+Name[is]=Póstfangaskrá
+Name[it]=Rubrica degli indirizzi
+Name[ja]=アドレス帳
+Name[ka]=წიგნáƒáƒ™áƒ˜
+Name[kk]=ÐдреÑтік кітапшаÑÑ‹
+Name[km]=សៀវភៅ​អាសយដ្ឋាន
+Name[lt]=Adresų knygelė
+Name[mk]=ÐдреÑар
+Name[ms]=Buku Alamat
+Name[nb]=Addressebok
+Name[nds]=Adressbook
+Name[ne]=ठेगाना पà¥à¤¸à¥à¤¤à¤¿à¤•à¤¾
+Name[nl]=Adresboek
+Name[nn]=Adressebok
+Name[pl]=Książka adresowa
+Name[pt]=Livro de Endereços
+Name[pt_BR]=Livro de Endereços
+Name[ro]=Carte de adrese
+Name[ru]=ÐдреÑÐ½Ð°Ñ ÐºÐ½Ð¸Ð³Ð°
+Name[se]=ÄŒujuhusgirji
+Name[sk]=Adresár
+Name[sl]=Adresar
+Name[sr]=ÐдреÑар
+Name[sr@Latn]=Adresar
+Name[sv]=Adressbok
+Name[ta]=à®®à¯à®•à®µà®°à®¿à®ªà¯à®ªà¯à®¤à¯à®¤à®•à®®à¯
+Name[tg]=Китоби адреÑÓ£
+Name[tr]=Adresdefteri
+Name[uk]=ÐдреÑна книга
+Name[uz]=Manzillar daftari
+Name[uz@cyrillic]=Манзиллар дафтари
+Name[zh_CN]=地å€ç°¿
+Name[zh_TW]=通訊錄
+Implemented=file
+ServiceTypes=KPilotConduit
+X-KDE-Library=conduit_address
diff --git a/kpilot/conduits/abbrowserconduit/abbrowserconduit.kcfg b/kpilot/conduits/abbrowserconduit/abbrowserconduit.kcfg
new file mode 100644
index 000000000..aed770641
--- /dev/null
+++ b/kpilot/conduits/abbrowserconduit/abbrowserconduit.kcfg
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
+ http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
+ <kcfgfile name="kpilot_addressconduitrc"/>
+ <group name="General">
+ <entry name="AddressbookType" key="Addressbook type" type="Enum">
+ <choices>
+ <choice name="eAbookResource"/>
+ <choice name="eAbookFile"/>
+ </choices>
+ <default>eAbookFile</default>
+ </entry>
+ <entry name="FileName" type="Path">
+ <default>$HOME/.kde/share/apps/kabc/std.vcf</default>
+ </entry>
+ <entry name="ArchiveDeleted" type="Bool">
+ <default>true</default>
+ </entry>
+ <entry name="ConflictResolution" key="ConflictResolve" type="Int">
+ <default>-1</default>
+ </entry>
+ <entry name="PilotOther" type="Enum">
+ <choices>
+ <choice name="eOtherPhone"/>
+ <choice name="eAssistant"/>
+ <choice name="eBusinessFax"/>
+ <choice name="eCarPhone"/>
+ <choice name="eEmail2"/>
+ <choice name="eHomeFax"/>
+ <choice name="eTelex"/>
+ <choice name="eTTYTTDPhone"/>
+ </choices>
+ <default>eOtherPhone</default>
+ </entry>
+ <entry name="PilotStreet" type="Enum">
+ <choices>
+ <choice name="ePilotStreetHome"/>
+ <choice name="ePilotStreetWork"/>
+ </choices>
+ <default>ePilotStreetHome</default>
+ </entry>
+ <entry name="PilotFax" type="Enum">
+ <choices>
+ <choice name="ePilotFaxHome"/>
+ <choice name="ePilotFaxWork"/>
+ </choices>
+ <default>ePilotFaxHome</default>
+ </entry>
+ <entry name="Custom0" key="Custom 0" type="Enum">
+ <choices label="eCustomEnum">
+ <choice name="eCustomField"/>
+ <choice name="eCustomBirthdate"/>
+ <choice name="eCustomURL"/>
+ <choice name="eCustomIM"/>
+ </choices>
+ <default>eCustomField</default>
+ </entry>
+ <entry name="Custom1" key="Custom 1" type="Enum">
+ <choices label="eCustomEnum">
+ </choices>
+ <default>eCustomField</default>
+ </entry>
+ <entry name="Custom2" key="Custom 2" type="Enum">
+ <choices label="eCustomEnum">
+ </choices>
+ <default>eCustomField</default>
+ </entry>
+ <entry name="Custom3" key="Custom 3" type="Enum">
+ <choices label="eCustomEnum">
+ </choices>
+ <default>eCustomField</default>
+ </entry>
+ <entry name="CustomDateFormat" type="String">
+ <default></default>
+ </entry>
+ </group>
+
+</kcfg>
diff --git a/kpilot/conduits/abbrowserconduit/kabcRecord.cc b/kpilot/conduits/abbrowserconduit/kabcRecord.cc
new file mode 100644
index 000000000..b5d68121a
--- /dev/null
+++ b/kpilot/conduits/abbrowserconduit/kabcRecord.cc
@@ -0,0 +1,710 @@
+/* KPilot
+**
+** Copyright (C) 2000,2001 by Dan Pilone
+** Copyright (C) 2002-2003 by Reinhold Kainhofer
+** Copyright (C) 2007 by Adriaan de Groot <groot@kde.org>
+**
+** The abbrowser conduit copies addresses from the Pilot's address book to
+** the KDE addressbook maintained via the kabc library. This file
+** deals with the actual copying of HH addresses to KABC addresses
+** and back again.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org.
+*/
+
+#include "options.h"
+
+#include <qregexp.h>
+
+#include <kglobal.h>
+#include <kabc/addressee.h>
+
+#include "kabcRecord.h"
+
+/**
+ * Okay, this is so that we can map the Pilot phone types to Phone Number
+ * types. Email addresses are NOT included in this map, and are handled
+ * separately (not in PhoneNumber at all). The Pilot has 8 different kinds
+ * of phone numbers (which may be *labeled* however you like). These
+ * need to be mapped to the things that KABC::PhoneNumber handles.
+ *
+ * From KABC::PhoneNumber
+ * enum Types { Home = 1, Work = 2, Msg = 4, Pref = 8, Voice = 16, Fax = 32,
+ * Cell = 64, Video = 128, Bbs = 256, Modem = 512, Car = 1024,
+ * Isdn = 2048, Pcs = 4096, Pager = 8192 };
+ *
+ *
+ * From PilotAddress:
+ * enum EPhoneType {
+ * eWork=0, eHome, eFax, eOther, eEmail, eMain,
+ * ePager, eMobile
+ * };
+ *
+ * This array must have as many elements as PilotAddress::PhoneType
+ * and its elements must be KABC::PhoneNumber::Types.
+ */
+
+static KABC::PhoneNumber::Types pilotToPhoneMap[8] = {
+ KABC::PhoneNumber::Work, // eWork
+ KABC::PhoneNumber::Home, // eHome,
+ KABC::PhoneNumber::Fax, // eFax,
+ (KABC::PhoneNumber::Types)0, // eOther -> wasn't mapped properly,
+ (KABC::PhoneNumber::Types)0, // eEmail -> shouldn't occur,
+ KABC::PhoneNumber::Home, // eMain
+ KABC::PhoneNumber::Pager, // ePager,
+ KABC::PhoneNumber::Cell // eMobile
+} ;
+
+KABC::PhoneNumber::List KABCSync::getPhoneNumbers(const PilotAddress &a)
+{
+ FUNCTIONSETUP;
+
+ KABC::PhoneNumber::List list;
+ QString test;
+
+ PhoneSlot shownPhone = a.getShownPhone();
+
+ DEBUGKPILOT << fname << ": preferred pilot index is: ["
+ << shownPhone << "], preferred phone number is: ["
+ << a.getField(shownPhone) << "]" << endl;
+
+ for (PhoneSlot i = PhoneSlot::begin(); i.isValid(); ++i)
+ {
+ // skip email entries
+ if ( a.getPhoneType(i) == PilotAddressInfo::eEmail )
+ {
+ continue;
+ }
+
+ test = a.getField(i);
+ // only look at this if the field is populated
+ if (test.isEmpty())
+ {
+ continue;
+ }
+
+ int phoneType = pilotToPhoneMap[a.getPhoneType(i)];
+
+ // only populate a PhoneNumber if we have a corresponding type
+ if (phoneType >=0)
+ {
+ // if this is the preferred phone number, set it as such
+ if (shownPhone == i)
+ {
+ phoneType |= KABC::PhoneNumber::Pref;
+ DEBUGKPILOT << fname << ": found preferred pilot index: ["
+ << i << "], text: [" << test << "]" << endl;
+ }
+ KABC::PhoneNumber ph(test, phoneType);
+ list.append(ph);
+ }
+ else
+ {
+ DEBUGKPILOT << fname << ": whoopsie. pilot phone number: ["
+ << test << "], index: [" << i << "], type: ["
+ << phoneType << "], has no corresponding PhoneNumber type." << endl;
+ }
+ }
+
+ DEBUGKPILOT << fname << ": returning: ["
+ << list.count() << "] phone numbers." << endl;
+
+ return list;
+}
+
+void KABCSync::setPhoneNumbers(const PilotAddressInfo &info,
+ PilotAddress &a,
+ const KABC::PhoneNumber::List &list)
+{
+ FUNCTIONSETUP;
+ QString test;
+
+ // clear all phone numbers (not e-mails) first
+ for ( PhoneSlot i = PhoneSlot::begin(); i.isValid() ; ++i )
+ {
+ PilotAddressInfo::EPhoneType ind = a.getPhoneType( i );
+ if (ind != PilotAddressInfo::eEmail)
+ {
+ a.setField(i, QString());
+ }
+ }
+
+ // now iterate through the list and for each PhoneNumber in the list,
+ // iterate through our phone types using our map and set the first one
+ // we find as the type of address for the Pilot
+ for(KABC::PhoneNumber::List::ConstIterator listIter = list.begin();
+ listIter != list.end(); ++listIter)
+ {
+ KABC::PhoneNumber phone = *listIter;
+
+ PilotAddressInfo::EPhoneType phoneType = PilotAddressInfo::eHome;
+
+ for ( int pilotPhoneType = PilotAddressInfo::eWork;
+ pilotPhoneType <= PilotAddressInfo::eMobile;
+ ++pilotPhoneType)
+ {
+ int phoneKey = pilotToPhoneMap[pilotPhoneType];
+ if ( phone.type() & phoneKey)
+ {
+ DEBUGKPILOT << fname << ": found pilot type: ["
+ << pilotPhoneType << "] ("
+ << info.phoneLabel( (PilotAddressInfo::EPhoneType)pilotPhoneType)
+ << ") for PhoneNumber: ["
+ << phone.number() << "]" << endl;
+
+ phoneType = (PilotAddressInfo::EPhoneType) pilotPhoneType;
+ break;
+ }
+ }
+ PhoneSlot fieldSlot =
+ a.setPhoneField(phoneType, phone.number(), PilotAddress::NoFlags);
+
+ // if this is the preferred phone number, then set it as such
+ if (fieldSlot.isValid() && (phone.type() & KABC::PhoneNumber::Pref))
+ {
+ DEBUGKPILOT << fname << ": found preferred PhoneNumber. "
+ << "setting showPhone to index: ["
+ << fieldSlot << "], PhoneNumber: ["
+ << phone.number() << "]" << endl;
+ a.setShownPhone( fieldSlot );
+ }
+
+ if (!fieldSlot.isValid())
+ {
+ DEBUGKPILOT << fname << ": Phone listing overflowed." << endl;
+ }
+ }
+
+ DEBUGKPILOT << fname << ": Pilot's showPhone now: ["
+ << a.getShownPhone() << "]." << endl;
+
+ // after setting the numbers, make sure that something sensible is set as the
+ // shownPhone on the Pilot if nothing is yet...
+ QString pref = a.getField(a.getShownPhone());
+ if (!a.getShownPhone().isValid() || pref.isEmpty())
+ {
+ DEBUGKPILOT << fname << ": Pilot's showPhone: ["
+ << a.getShownPhone()
+ << "] not properly set to a default."
+ << endl;
+
+ for (PhoneSlot i = PhoneSlot::begin(); i.isValid(); ++i)
+ {
+ pref = a.getField(i);
+ if (!pref.isEmpty())
+ {
+ a.setShownPhone( i );
+ DEBUGKPILOT << fname << ": Pilot's showPhone now: ["
+ << a.getShownPhone()
+ << "], and that's final." << endl;
+ break;
+ }
+ }
+ }
+}
+
+unsigned int KABCSync::bestMatchedCategory(const QStringList &pccategories,
+ const PilotAddressInfo &info,
+ unsigned int hhcategory)
+{
+ FUNCTIONSETUP;
+ // No categories in list, must be unfiled
+ if (pccategories.size()<1)
+ {
+ return Pilot::Unfiled;
+ }
+
+ // See if the suggested hhcategory is in the list, and if
+ // so that is the best match.
+ if (Pilot::validCategory(hhcategory) &&
+ pccategories.contains(info.categoryName(hhcategory)))
+ {
+ return hhcategory;
+ }
+
+ // Look for the first category from the list which is available on
+ // the handheld as well.
+ for(QStringList::ConstIterator it = pccategories.begin(); it != pccategories.end(); ++it)
+ {
+ // Do not map unknown to unfiled when looking for category
+ int c = info.findCategory( *it, false );
+ if ( c >= 0)
+ {
+ Q_ASSERT(Pilot::validCategory(c));
+ return c;
+ }
+ }
+
+ // didn't find anything. return null
+ return Pilot::Unfiled;
+}
+
+void KABCSync::setCategory(KABC::Addressee & abEntry, const QString &cat)
+{
+ if ( (!cat.isEmpty()))
+ {
+ abEntry.insertCategory(cat);
+ }
+}
+
+
+QString KABCSync::getFieldForHHCustom(
+ const unsigned int index,
+ const KABC::Addressee &abEntry,
+ const KABCSync::Settings &settings)
+{
+ FUNCTIONSETUPL(4);
+
+ QString retval;
+
+ if (index>3)
+ {
+ WARNINGKPILOT << "Bad index number " << index << endl;
+ retval = QString();
+ }
+ if (settings.customMapping().count() != 4)
+ {
+ WARNINGKPILOT << "Mapping does not have 4 elements." << index << endl;
+ retval = QString();
+ }
+
+ switch (settings.custom(index))
+ {
+ case eCustomBirthdate:
+ if (settings.dateFormat().isEmpty())
+ {
+ retval = KGlobal::locale()->formatDate(abEntry.birthday().date());
+ }
+ else
+ {
+ QString tmpfmt(KGlobal::locale()->dateFormat());
+ KGlobal::locale()->setDateFormat(settings.dateFormat());
+ QString ret(KGlobal::locale()->formatDate(abEntry.birthday().date()));
+ KGlobal::locale()->setDateFormat(tmpfmt);
+ retval = ret;
+ }
+ break;
+ case eCustomURL:
+ retval = abEntry.url().url();
+ break;
+ case eCustomIM:
+ retval = abEntry.custom(CSL1("KADDRESSBOOK"), CSL1("X-IMAddress"));
+ break;
+ case eCustomField:
+ default:
+ retval = abEntry.custom(appString, CSL1("CUSTOM")+QString::number(index));
+ break;
+ }
+
+ return retval;
+}
+
+void KABCSync::setFieldFromHHCustom(
+ const unsigned int index,
+ KABC::Addressee &abEntry,
+ const QString &value,
+ const KABCSync::Settings &settings)
+{
+ FUNCTIONSETUPL(4);
+
+ if (index>3)
+ {
+ WARNINGKPILOT << "Bad index number " << index << endl;
+ return;
+ }
+ if (settings.customMapping().count() != 4)
+ {
+ WARNINGKPILOT << "Mapping does not have 4 elements." << index << endl;
+ return;
+ }
+
+ switch (settings.custom(index))
+ {
+ case eCustomBirthdate:
+ {
+ QDate bdate;
+ bool ok=false;
+ if (settings.dateFormat().isEmpty())
+ {
+ // empty format means use locale setting
+ bdate=KGlobal::locale()->readDate(value, &ok);
+ }
+ else
+ {
+ // use given format
+ bdate=KGlobal::locale()->readDate(value, settings.dateFormat(), &ok);
+ }
+
+ if (!ok)
+ {
+ QString format = KGlobal::locale()->dateFormatShort();
+ QRegExp re(CSL1("%[yY][^%]*"));
+ format.remove(re); // Remove references to year and following punctuation
+ bdate = KGlobal::locale()->readDate(value, format, &ok);
+ }
+ DEBUGKPILOT << "Birthdate from " << index << "-th custom field: "
+ << bdate.toString() << endl;
+ DEBUGKPILOT << "Is Valid: " << bdate.isValid() << endl;
+ if (bdate.isValid())
+ {
+ abEntry.setBirthday(bdate);
+ }
+ else
+ {
+ abEntry.insertCustom(CSL1("KADDRESSBOOK"), CSL1("X-Birthday"), value);
+ }
+ break;
+ }
+ case eCustomURL:
+ abEntry.setUrl(value);
+ break;
+ case eCustomIM:
+ abEntry.insertCustom(CSL1("KADDRESSBOOK"), CSL1("X-IMAddress"), value);
+ break;
+ case eCustomField:
+ default:
+ abEntry.insertCustom(appString, CSL1("CUSTOM")+QString::number(index), value);
+ break;
+ }
+}
+
+
+/** First search for a preferred address. If we don't have one, search
+ * for home or work as specified in the config dialog. If we don't have
+ * such one, either, search for the other type. If we still have no luck,
+ * return an address with preferred + home/work flag (from config dlg). */
+KABC::Address KABCSync::getAddress(const KABC::Addressee &abEntry, const KABCSync::Settings &s)
+{
+ // preferhome == (AbbrowserSettings::pilotStreet==0)
+
+ // Check for preferred address first
+ KABC::Address ad(abEntry.address(KABC::Address::Pref));
+ if (!ad.isEmpty()) return ad;
+
+ // Look for home or work, whichever is preferred
+ int type = s.preferHome() ? KABC::Address::Home : KABC::Address::Work;
+ ad=abEntry.address(type);
+ if (!ad.isEmpty()) return ad;
+
+ // Switch preference if still none found
+ type = !s.preferHome() ? KABC::Address::Home : KABC::Address::Work;
+ ad=abEntry.address(type);
+ if (!ad.isEmpty()) return ad;
+
+ // Last-ditch attempt; see if there is a preferred home or work address
+ type = s.preferHome() ? KABC::Address::Home : KABC::Address::Work;
+ return abEntry.address(type | KABC::Address::Pref);
+}
+
+
+QString KABCSync::getFieldForHHOtherPhone(const KABC::Addressee & abEntry, const KABCSync::Settings &s)
+{
+ switch(s.fieldForOtherPhone())
+ {
+ case eOtherPhone:
+ return abEntry.phoneNumber(0).number();
+ case eAssistant:
+ return abEntry.custom(CSL1("KADDRESSBOOK"), CSL1("AssistantsName"));
+ case eBusinessFax:
+ return abEntry.phoneNumber(KABC::PhoneNumber::Fax | KABC::PhoneNumber::Work).number();
+ case eCarPhone:
+ return abEntry.phoneNumber(KABC::PhoneNumber::Car).number();
+ case eEmail2:
+ return abEntry.emails().first();
+ case eHomeFax:
+ return abEntry.phoneNumber(KABC::PhoneNumber::Fax | KABC::PhoneNumber::Home).number();
+ case eTelex:
+ return abEntry.phoneNumber(KABC::PhoneNumber::Bbs).number();
+ case eTTYTTDPhone:
+ return abEntry.phoneNumber(KABC::PhoneNumber::Pcs).number();
+ default:
+ return QString::null;
+ }
+}
+
+void KABCSync::setFieldFromHHOtherPhone(KABC::Addressee & abEntry, const QString &nr, const KABCSync::Settings &s)
+{
+ int phoneType = 0;
+ switch (s.fieldForOtherPhone())
+ {
+ // One very special case which doesn't even map to a real phone type in KABC
+ case eAssistant:
+ abEntry.insertCustom(CSL1("KADDRESSBOOK"), CSL1("AssistantsName"), nr);
+ return;
+ // Special case: map phone to email, needs different handling.
+ case eEmail2:
+ abEntry.insertEmail(nr);
+ return;
+ // Remaining cases all map to various phone types
+ case eOtherPhone:
+ phoneType = 0;
+ break;
+ case eBusinessFax:
+ phoneType = KABC::PhoneNumber::Fax | KABC::PhoneNumber::Work;
+ break;
+ case eHomeFax:
+ phoneType = KABC::PhoneNumber::Fax | KABC::PhoneNumber::Home;
+ break;
+ case eCarPhone:
+ phoneType = KABC::PhoneNumber::Car;
+ break;
+ case eTelex:
+ phoneType = KABC::PhoneNumber::Bbs;
+ break;
+ case eTTYTTDPhone:
+ phoneType = KABC::PhoneNumber::Pcs;
+ break;
+ default:
+ WARNINGKPILOT << "Unknown phone mapping " << s.fieldForOtherPhone() << endl;
+ phoneType = 0;
+ }
+ KABC::PhoneNumber phone = abEntry.phoneNumber(phoneType);
+ phone.setNumber(nr);
+ phone.setType(phoneType); // Double-check in case there was no phonenumber of given type
+ abEntry.insertPhoneNumber(phone);
+}
+
+void KABCSync::setAddress(PilotAddress &toPilotAddr,
+ const KABC::Address & abAddress)
+{
+ toPilotAddr.setField(entryAddress, abAddress.street());
+ toPilotAddr.setField(entryCity, abAddress.locality());
+ toPilotAddr.setField(entryState, abAddress.region());
+ toPilotAddr.setField(entryZip, abAddress.postalCode());
+ toPilotAddr.setField(entryCountry, abAddress.country());
+}
+
+
+bool KABCSync::isArchived(const KABC::Addressee &addr)
+{
+ return addr.custom(KABCSync::appString, KABCSync::flagString) == QString::number(SYNCDEL);
+}
+
+void KABCSync::makeArchived(KABC::Addressee &addr)
+{
+ FUNCTIONSETUP;
+ addr.insertCustom(KABCSync::appString, KABCSync::flagString, QString::number(SYNCDEL));
+ addr.removeCustom(KABCSync::appString, KABCSync::idString);
+}
+
+
+
+
+void KABCSync::copy(PilotAddress &toPilotAddr,
+ const KABC::Addressee &fromAbEntry,
+ const PilotAddressInfo &appInfo,
+ const KABCSync::Settings &syncSettings)
+{
+ FUNCTIONSETUP;
+
+ toPilotAddr.setDeleted(false);
+
+ // don't do a reset since this could wipe out non copied info
+ //toPilotAddr.reset();
+ toPilotAddr.setField(entryLastname, fromAbEntry.familyName());
+ toPilotAddr.setField(entryFirstname, fromAbEntry.givenName());
+ toPilotAddr.setField(entryCompany, fromAbEntry.organization());
+ toPilotAddr.setField(entryTitle, fromAbEntry.prefix());
+ toPilotAddr.setField(entryNote, fromAbEntry.note());
+
+ // do email first, to ensure they get stored
+ toPilotAddr.setEmails(fromAbEntry.emails());
+
+ // now in one fell swoop, set all phone numbers from the Addressee. Note,
+ // we don't need to differentiate between Fax numbers here--all Fax numbers
+ // (Home Fax or Work Fax or just plain old Fax) will get synced to the Pilot
+ KABCSync::setPhoneNumbers(appInfo,toPilotAddr,fromAbEntry.phoneNumbers());
+
+ // Other field is an oddball and if the user has more than one field set
+ // as "Other" then only one will be carried over.
+ QString oth = KABCSync::getFieldForHHOtherPhone(fromAbEntry,syncSettings);
+ DEBUGKPILOT << fname << ": putting: ["<<oth<<"] into Palm's other"<<endl;
+ toPilotAddr.setPhoneField(PilotAddressInfo::eOther,
+ oth, PilotAddress::Replace);
+
+ KABC::Address homeAddress = KABCSync::getAddress(fromAbEntry, syncSettings);
+ KABCSync::setAddress(toPilotAddr, homeAddress);
+
+ // Process the additional entries from the Palm(the palm database app block tells us the name of the fields)
+ unsigned int customIndex = 0;
+ unsigned int hhField = entryCustom1;
+
+ for ( ; customIndex<4; ++customIndex,++hhField )
+ {
+ toPilotAddr.setField(hhField,getFieldForHHCustom(customIndex,fromAbEntry,syncSettings));
+ }
+
+ int categoryForHH = KABCSync::bestMatchedCategory(fromAbEntry.categories(),
+ appInfo,toPilotAddr.category());
+ toPilotAddr.setCategory(categoryForHH);
+
+ if (isArchived(fromAbEntry))
+ {
+ toPilotAddr.setArchived( true );
+ }
+ else
+ {
+ toPilotAddr.setArchived( false );
+ }
+}
+
+void KABCSync::copy(KABC::Addressee &toAbEntry,
+ const PilotAddress &fromPiAddr,
+ const PilotAddressInfo &appInfo,
+ const KABCSync::Settings &syncSettings)
+{
+ FUNCTIONSETUP;
+
+ // copy straight forward values
+ toAbEntry.setFamilyName(fromPiAddr.getField(entryLastname));
+ toAbEntry.setGivenName(fromPiAddr.getField(entryFirstname));
+ toAbEntry.setOrganization(fromPiAddr.getField(entryCompany));
+ toAbEntry.setPrefix(fromPiAddr.getField(entryTitle));
+ toAbEntry.setNote(fromPiAddr.getField(entryNote));
+
+ // set the formatted name
+ // TODO this is silly and should be removed soon.
+ toAbEntry.setFormattedName(toAbEntry.realName());
+
+ // copy the phone stuff
+ // first off, handle the e-mail addresses as a group and separate from
+ // the other phone number fields
+ toAbEntry.setEmails(fromPiAddr.getEmails());
+
+ // going from Pilot to kabc, we need to clear out all phone records in kabc
+ // so that they can be set from the Pilot. If we do not do this, then records
+ // will be left in kabc when they are removed from the Pilot and we'll look
+ // broken.
+ KABC::PhoneNumber::List old = toAbEntry.phoneNumbers();
+ for (KABC::PhoneNumber::List::Iterator it = old.begin(); it != old.end(); ++it) {
+ KABC::PhoneNumber phone = *it;
+ toAbEntry.removePhoneNumber(phone);
+ }
+
+ // now, get the phone numbers from the Pilot and set them one at a time in kabc
+ KABC::PhoneNumber::List phones = KABCSync::getPhoneNumbers(fromPiAddr);
+ for (KABC::PhoneNumber::List::Iterator it = phones.begin(); it != phones.end(); ++it) {
+ KABC::PhoneNumber phone = *it;
+ // check for fax number if it is one, set the type per the user's direction
+ if (phone.type() & KABC::PhoneNumber::Fax)
+ {
+ phone.setType(syncSettings.faxTypeOnPC());
+ }
+ toAbEntry.insertPhoneNumber(phone);
+ }
+
+ // Note: this is weird, and it may cause data to not be synced if there is
+ // more than one "Other" field being used on the Pilot, since only one will
+ // be synced in either direction.
+ KABCSync::setFieldFromHHOtherPhone(toAbEntry,
+ fromPiAddr.getPhoneField(PilotAddressInfo::eOther),syncSettings);
+
+ // going from Pilot to kabc, we need to clear out all addresses in kabc
+ // so that they can be set from the Pilot. If we do not do this, then records
+ // will be left in kabc when they are removed from the Pilot and we'll look
+ // broken.
+ KABC::Address::List oAddr = toAbEntry.addresses();
+ for (KABC::Address::List::Iterator it = oAddr.begin(); it != oAddr.end(); ++it) {
+ const KABC::Address addr = *it;
+ toAbEntry.removeAddress(addr);
+ }
+ KABC::Address homeAddress = KABCSync::getAddress(toAbEntry,syncSettings);
+ homeAddress.setStreet(fromPiAddr.getField(entryAddress));
+ homeAddress.setLocality(fromPiAddr.getField(entryCity));
+ homeAddress.setRegion(fromPiAddr.getField(entryState));
+ homeAddress.setPostalCode(fromPiAddr.getField(entryZip));
+ homeAddress.setCountry(fromPiAddr.getField(entryCountry));
+ toAbEntry.insertAddress(homeAddress);
+
+ unsigned int customIndex = 0;
+ unsigned int hhField = entryCustom1;
+
+ for ( ; customIndex<4; ++customIndex,++hhField )
+ {
+ KABCSync::setFieldFromHHCustom(customIndex,
+ toAbEntry,
+ fromPiAddr.getField(hhField),
+ syncSettings);
+ }
+
+ // copy the fromPiAddr pilot id to the custom field KPilot_Id;
+ // pilot id may be zero(since it could be new) but couldn't hurt
+ // to even assign it to zero; let's us know what state the
+ // toAbEntry is in
+ toAbEntry.insertCustom(KABCSync::appString, KABCSync::idString, QString::number(fromPiAddr.id()));
+
+ KABCSync::setCategory(toAbEntry, appInfo.categoryName(fromPiAddr.category()));
+
+ showAddressee(toAbEntry);
+}
+
+void KABCSync::showAddressee(const KABC::Addressee & abAddress)
+{
+ FUNCTIONSETUP;
+#ifdef DEBUG
+ DEBUGKPILOT << "\tAbbrowser Contact Entry" << endl;
+ if (abAddress.isEmpty())
+ {
+ DEBUGKPILOT<< "\t\tEMPTY"<<endl;
+ return;
+ }
+ DEBUGKPILOT << "\t\tLast name = " << abAddress.familyName() << endl;
+ DEBUGKPILOT << "\t\tFirst name = " << abAddress.givenName() << endl;
+ DEBUGKPILOT << "\t\tCompany = " << abAddress.organization() << endl;
+ DEBUGKPILOT << "\t\tJob Title = " << abAddress.prefix() << endl;
+ DEBUGKPILOT << "\t\tNote = " << abAddress.note() << endl;
+ DEBUGKPILOT << "\t\tCategory = " << abAddress.categories().first() << endl;
+ DEBUGKPILOT << "\t\tEmail = " << abAddress.emails().join(",") << endl;
+
+ KABC::PhoneNumber::List phs = abAddress.phoneNumbers();
+ for (KABC::PhoneNumber::List::Iterator it = phs.begin(); it != phs.end(); ++it) {
+ KABC::PhoneNumber phone = *it;
+ DEBUGKPILOT << "\t\t" << phone.label()
+ << "= " << phone.number() << endl;
+ }
+
+ KABC::Address::List ads = abAddress.addresses();
+ for (KABC::Address::List::Iterator it = ads.begin(); it != ads.end(); ++it) {
+ const KABC::Address addr = *it;
+ DEBUGKPILOT << "\t\tAddress = " << addr.street() <<endl;
+ DEBUGKPILOT << "\t\tLocality = " << addr.locality() <<endl;
+ DEBUGKPILOT << "\t\tRegion = " << addr.region() <<endl;
+ DEBUGKPILOT << "\t\tPostal code = " << addr.postalCode() <<endl;
+ DEBUGKPILOT << "\t\tCountry = " << addr.country() <<endl << endl;
+ }
+#else
+ Q_UNUSED( abAddress );
+#endif
+}
+
+
+
+
+KABCSync::Settings::Settings() :
+ fDateFormat(),
+ fCustomMapping(4), // Reserve space for 4 elements, value 0 == CustomField
+ fOtherPhone(eOtherPhone),
+ fPreferHome(true),
+ fFaxTypeOnPC(KABC::PhoneNumber::Fax | KABC::PhoneNumber::Home)
+{
+}
+
diff --git a/kpilot/conduits/abbrowserconduit/kabcRecord.h b/kpilot/conduits/abbrowserconduit/kabcRecord.h
new file mode 100644
index 000000000..13a3e2694
--- /dev/null
+++ b/kpilot/conduits/abbrowserconduit/kabcRecord.h
@@ -0,0 +1,263 @@
+#ifndef _KPILOT_KABCRECORD_H
+#define _KPILOT_KABCRECORD_H
+/* KPilot
+**
+** Copyright (C) 2000,2001 by Dan Pilone
+** Copyright (C) 2002-2003 by Reinhold Kainhofer
+** Copyright (C) 2007 by Adriaan de Groot <groot@kde.org>
+**
+** The abbrowser conduit copies addresses from the Pilot's address book to
+** the KDE addressbook maintained via the kabc library. This file
+** deals with the actual copying of HH addresses to KABC addresses
+** and back again.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org.
+*/
+
+#include <qvaluevector.h>
+
+#include <kabc/phonenumber.h>
+
+#include "pilotAddress.h"
+
+#define SYNCNONE 0
+#define SYNCMOD 1
+#define SYNCDEL 3
+
+namespace KABCSync
+{
+ // This duplicates values from the config settings,
+ // and must be kept in sync if new settings are added
+ // -- there are compile time checks for this in the
+ // abbrowser conduit code.
+ enum MappingForOtherPhone {
+ eOtherPhone=0,
+ eAssistant,
+ eBusinessFax,
+ eCarPhone,
+ eEmail2,
+ eHomeFax,
+ eTelex,
+ eTTYTTDPhone
+ } ;
+
+ enum MappingForCustomField {
+ eCustomField=0,
+ eCustomBirthdate,
+ eCustomURL,
+ eCustomIM
+ } ;
+
+ class Settings
+ {
+ public:
+ Settings();
+ QString dateFormat() const
+ {
+ return fDateFormat;
+ }
+ void setDateFormat(const QString& s)
+ {
+ fDateFormat = s;
+ }
+
+ const QValueVector<int> &customMapping() const
+ {
+ return fCustomMapping;
+ }
+ void setCustomMapping(const QValueVector<int> &v)
+ {
+ if (v.count()==4)
+ {
+ fCustomMapping = v;
+ }
+ }
+ int custom(int index) const
+ {
+ if ( (index<0) || (index>3) )
+ {
+ return 0;
+ }
+ else
+ {
+ return fCustomMapping[index];
+ }
+ }
+
+ int fieldForOtherPhone() const
+ {
+ return fOtherPhone;
+ }
+ void setFieldForOtherPhone(int v)
+ {
+ fOtherPhone = v;
+ }
+
+ bool preferHome() const
+ {
+ return fPreferHome;
+ }
+ void setPreferHome(bool v)
+ {
+ fPreferHome = v;
+ }
+
+ int faxTypeOnPC() const
+ {
+ return fFaxTypeOnPC;
+ }
+ void setFaxTypeOnPC(int v)
+ {
+ fFaxTypeOnPC = v;
+ }
+ private:
+ QString fDateFormat;
+ QValueVector<int> fCustomMapping;
+ int fOtherPhone;
+ bool fPreferHome;
+ int fFaxTypeOnPC;
+ } ;
+
+
+ /** Return a list of all the phone numbers (max. 8) set in this
+ * handheld entry @p a . Email entries are ignored.
+ */
+ KABC::PhoneNumber::List getPhoneNumbers(const PilotAddress &a);
+
+ /** Set the phone numbers from @p list in the handheld entry
+ * @p a (with info block @p info providing the mapping of category
+ * names and some other fiddly stuff) as far as possible.
+ * @em No overflow handling is done at all. If the desktop has
+ * more than 5 phone entries, the remainder are dropped.
+ */
+ void setPhoneNumbers(const PilotAddressInfo &info,
+ PilotAddress &a,
+ const KABC::PhoneNumber::List &list);
+
+ /** Given a list of category names from the KDE side (e.g. attached
+ * to a PC-based Addressee) @p categorynames , look for the
+ * category @em best matching the category @p category
+ * in the appinfo block @p info . Here, best is defined as follows:
+ * - if the name of category @p category is in the list, use it
+ * - otherwise use the first category from the list that is a valid
+ * category on the handheld.
+ * - use Pilot::Unfiled if none match.
+ *
+ * @return Category index that best matches.
+ * @return Pilot::Unfiled if no best match.
+ */
+ unsigned int bestMatchedCategory(const QStringList &categorynames,
+ const PilotAddressInfo &info,
+ unsigned int category);
+
+ /** As above, but return the name of the category. */
+ inline QString bestMatchedCategoryName(const QStringList &categorynames,
+ const PilotAddressInfo &info,
+ unsigned int category)
+ {
+ return info.categoryName(
+ bestMatchedCategory(categorynames, info, category));
+ }
+
+ /** Give the addressee @p abEntry the category @p cat (leaving
+ * existing category assignments intact).
+ */
+ void setCategory(KABC::Addressee &abEntry, const QString &cat);
+
+ /* These are string identifiers used for custom properties in the addressees,
+ * used to store KPilot-specific settings.
+ */
+ const QString appString=CSL1("KPILOT"); ///< Identifier for the application
+ const QString flagString=CSL1("Flag"); ///< Flags: synced or not
+ const QString idString=CSL1("RecordID"); ///< Record ID on HH for this addressee
+
+
+ /** Get the string value for HH custom field @p index (0..3) from the addressee
+ * @p abEntry . Which @em actual field this is depends on the mapping
+ * of custom HH fields to PC fields. This mapping is given by the @p customMapping
+ * which may be created from the conduit settings or by hand. Since one of the
+ * possible actual fields is "birthday," which needs formatting, use the date format
+ * string @p dateFormat. If this is empty, use the locale setting.
+ *
+ * @return String value for HH custom field @p index
+ * @return Null QString on error (is also a valid return value)
+ */
+ QString getFieldForHHCustom(
+ unsigned int index,
+ const KABC::Addressee &abEntry,
+ const Settings &settings);
+
+ /** Set a field of the PC @p abEntry address from the custom HH field.
+ * Use value @p value . The value comes from custom field @p index
+ * using the interpretation of custom fields @p customMapping . Because
+ * one of the interpretations includes the birthday, use the date format
+ * @p dateFormat ; if empty, use the local format when setting dates from the HH.
+ */
+ void setFieldFromHHCustom(
+ const unsigned int index,
+ KABC::Addressee &abEntry,
+ const QString &value,
+ const Settings &settings);
+
+ /** The HH has a phone type "other" which may be mapped to any one of
+ * several PC side phone numbers. Return the right one depending in the mapping.
+ *
+ * @note @p mappingForOther should come from AbbrowserSettings::pilotOther()
+ */
+ QString getFieldForHHOtherPhone(const KABC::Addressee &abEntry, const Settings &s);
+
+ /** The HH has a phone type "other" which may be mapped to any one
+ * of several PC side phone numbers. Store the number @p nr in the
+ * PC side phone field indicated by @p mappingForOther .
+ *
+ * @note @p mappingForOther should come from AbbrowserSettings::pilotOther()
+ */
+ void setFieldFromHHOtherPhone(KABC::Addressee &abEntry, const QString &nr, const Settings &s);
+
+ /** Returns the address portion of an addressee. Since the HH can only store
+ * one address, we return the preferred address (if the Addressee @p abEntry
+ * has one) and then either home or business depending on @p preferHome
+ * and if that doesn't exist, the other one and if @em that doesn't exist,
+ * return the preferred home or work address if it exists.
+ */
+ KABC::Address getAddress(const KABC::Addressee &abEntry, const Settings &);
+
+ /** Set the address fields of the HH record from the @p abAddress . */
+ void setAddress(PilotAddress &toPilotAddr, const KABC::Address &abAddress);
+
+ bool isArchived(const KABC::Addressee &);
+ void makeArchived(KABC::Addressee &);
+
+ void copy(PilotAddress &toPilotAddr,
+ const KABC::Addressee &fromAbEntry,
+ const PilotAddressInfo &appInfo,
+ const Settings &syncSettings);
+ void copy(KABC::Addressee &toAbEntry,
+ const PilotAddress &fromPiAddr,
+ const PilotAddressInfo &appInfo,
+ const Settings &syncSettings);
+
+ void showAddressee(const KABC::Addressee &);
+}
+
+#endif
+
diff --git a/kpilot/conduits/abbrowserconduit/kaddressbookConduit.ui b/kpilot/conduits/abbrowserconduit/kaddressbookConduit.ui
new file mode 100644
index 000000000..6447caa07
--- /dev/null
+++ b/kpilot/conduits/abbrowserconduit/kaddressbookConduit.ui
@@ -0,0 +1,746 @@
+<!DOCTYPE UI><UI version="3.1" stdsetdef="1">
+<class>AbbrowserWidget</class>
+<author>Adriaan de Groot and David Bishop</author>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>Form2</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>645</width>
+ <height>287</height>
+ </rect>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QTabWidget" row="0" column="0">
+ <property name="name">
+ <cstring>tabWidget</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>General</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer row="3" column="0">
+ <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>50</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QButtonGroup" row="0" column="0">
+ <property name="name">
+ <cstring>fSyncDestination</cstring>
+ </property>
+ <property name="title">
+ <string>Sync Destination</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QRadioButton" row="0" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>fSyncStdAbook</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Standard addressbook</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Select this option to synchronize with KDE's standard addressbook (i.e. the addressbook that you edit in KAddressBook, and which you use in KMail)&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="1" column="0">
+ <property name="name">
+ <cstring>fSyncFile</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>vCard &amp;file:</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Select this option to use a specific address book file, instead of the standard KDE address book. This file must be in the vCard format (.vcf). Type the location of this file in the edit box or select it clicking the file picker button.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="KURLRequester" row="1" column="1">
+ <property name="name">
+ <cstring>fAbookFile</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Enter the vCard file name here or select it by clicking the file picker button. vCard is a standard format for exchanging contact information. &lt;/qt&gt;</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QCheckBox" row="2" column="0">
+ <property name="name">
+ <cstring>fArchive</cstring>
+ </property>
+ <property name="text">
+ <string>Store &amp;archived records in the KDE addressbook</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;If you delete an address on your handheld, you can determine if it should be archived on the PC. If you check that and this checkbox, the address will be added to your addressbook, but no longer synchronized with the handheld.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Conflicts</string>
+ </attribute>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>groupBox4</cstring>
+ </property>
+ <property name="title">
+ <string>Conflict Resolution</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>textLabel1_2_2</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>4</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Conflict &amp;resolution:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>fConflictResolution</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Select in this list how conflicting entries (entries which were edited both on your handheld and on the PC) are resolved. Possibly values are "Use KPilot's Global Setting" to use the settings defined in KPilot HotSync configuration, "Ask User" to let you decide case by case, "Do Nothing" to allow the entries to be different, "PC overrides", "Handheld overrides", "Use values from last sync" and "Use both entries" to create a new entry on both the PC and handheld.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QComboBox" row="1" column="1">
+ <item>
+ <property name="text">
+ <string>Use KPilot's Global Setting</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Ask User</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Do Nothing</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Handheld Overrides</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>PC Overrides</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Values From Last Sync (if possible)</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Use Both Entries</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>fConflictResolution</cstring>
+ </property>
+ <property name="currentItem">
+ <number>6</number>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Select in this list how conflicting entries (entries which were edited both on your handheld and on the PC) are resolved. Possibly values are "Use KPilot's Global Setting" to use the settings defined in KPilot HotSync configuration, "Ask User" to let you decide case by case, "Do Nothing" to allow the entries to be different, "PC overrides", "Handheld overrides", "Use values from last sync" and "Use both entries" to create a new entry on both the PC and handheld.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>textLabel1_7</cstring>
+ </property>
+ <property name="text">
+ <string>&lt;p&gt;Select the default action if an event was modified on both sides here. &lt;/p&gt;</string>
+ </property>
+ <property name="alignment">
+ <set>WordBreak|AlignJustify|AlignVCenter</set>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer6</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>41</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Fields</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>TextLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Handheld other phone:</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Select which KAddressBook field should be used to store the Pilot's &amp;quot;Other&amp;quot; phone here.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QComboBox" row="0" column="1">
+ <item>
+ <property name="text">
+ <string>Other Phone</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Assistant</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Business Fax</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Car Phone</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Email 2</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Home Fax</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Telex</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>TTY/TTD Phone</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>fOtherPhone</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>&lt;qt&gt;Select which KAddressBook field should be used to store the Pilot's &amp;quot;Other&amp;quot; phone here.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>TextLabel4</cstring>
+ </property>
+ <property name="text">
+ <string>Handheld street address:</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Select which KAddressBook field should be used to store the Pilot's Street Address here.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QComboBox" row="1" column="1">
+ <item>
+ <property name="text">
+ <string>Preferred, then Home Address</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Preferred, then Business Address</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>fAddress</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Select which KAddressBook field should be used to store the Pilot's Street Address here.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="2" column="0">
+ <property name="name">
+ <cstring>TextLabel5</cstring>
+ </property>
+ <property name="text">
+ <string>Handheld fax:</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Select which KAddressBook field should be used to store the Fax number from the Pilot here.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QComboBox" row="2" column="1">
+ <item>
+ <property name="text">
+ <string>Home Fax</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Business Fax</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>fFax</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Select which KAddressBook field should be used to store the Fax number from the Pilot here.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <spacer row="3" column="0">
+ <property name="name">
+ <cstring>Spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>0</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Custom Fields</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Handheld custom field 1:</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Select the field from this list that represents best the meaning given by your use of the first custom field on your handheld.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>textLabel1_2</cstring>
+ </property>
+ <property name="text">
+ <string>Handheld custom field 2:</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Select the field from this list that represents best the meaning given by your use of the second custom field on your handheld.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="2" column="0">
+ <property name="name">
+ <cstring>textLabel1_3</cstring>
+ </property>
+ <property name="text">
+ <string>Handheld custom field 3:</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Select the field from this list that represents best the meaning given by your use of the third custom field on your handheld.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="3" column="0">
+ <property name="name">
+ <cstring>textLabel1_4</cstring>
+ </property>
+ <property name="text">
+ <string>Handheld custom field 4:</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Select the field from this list that represents best the meaning given by your use of the fourth custom field on your handheld.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QComboBox" row="0" column="1">
+ <item>
+ <property name="text">
+ <string>Store as Custom Field</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Birthdate</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>URL</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>IM Address (ICQ, MS, ...)</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>fCustom0</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>&lt;qt&gt;Select the field from this list that represents best the meaning given by your use of the first custom field on your handheld.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QComboBox" row="1" column="1">
+ <item>
+ <property name="text">
+ <string>Store as Custom Field</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Birthdate</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>URL</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>IM Address (ICQ, MSN, ...)</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>fCustom1</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>&lt;qt&gt;Select the field from this list that represents best the meaning given by your use of the second custom field on your handheld.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QComboBox" row="2" column="1">
+ <item>
+ <property name="text">
+ <string>Store as Custom Field</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Birthdate</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>URL</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>IM Address (ICQ, MSN, ...)</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>fCustom2</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>&lt;qt&gt;Select the field from this list that represents best the meaning given by your use of the third custom field on your handheld.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QComboBox" row="3" column="1">
+ <item>
+ <property name="text">
+ <string>Store as Custom Field</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Birthdate</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>URL</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>IM Address (ICQ, MSN, ...)</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>fCustom3</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>&lt;qt&gt;Select the field from this list that represents best the meaning given by your use of the fourth custom field on your handheld.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="Line" row="4" column="0" rowspan="1" colspan="2">
+ <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="QLabel" row="5" column="0" rowspan="2" colspan="1">
+ <property name="name">
+ <cstring>textLabel1_5</cstring>
+ </property>
+ <property name="text">
+ <string>Date &amp;format:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>fCustomDate</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Select the birthdate format here, if you selected "birthdate" for any of the custom fields above. Possible placeholders are:&lt;br&gt; %d for the day, %m for the month, %y for the two-digit year, %Y for the four-digit year. For example, %d.%m.%Y would generate a date like 27.3.1952, while %m/%d/%y would write the same date as 03/27/52. &lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QComboBox" row="6" column="1">
+ <item>
+ <property name="text">
+ <string>Locale Settings</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>%d.%m.%Y</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>%d.%m.%y</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>%d/%m/%Y</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>%d/%m/%y</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>%m/%d/%Y</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>%m/%d/%y</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>fCustomDate</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="editable">
+ <bool>true</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Select the birthdate format here, if you selected "birthdate" for any of the custom fields above. Possible placeholders are:&lt;br&gt; %d for the day, %m for the month, %y for the two-digit year, %Y for the four-digit year. For example, %d.%m.%Y would generate a date like 27.3.1952, while %m/%d/%y would write the same date as 03/27/52. &lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <spacer row="8" column="1">
+ <property name="name">
+ <cstring>spacer5</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>31</width>
+ <height>30</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+ </widget>
+ </widget>
+ </grid>
+</widget>
+<connections>
+ <connection>
+ <sender>fSyncFile</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>fAbookFile</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+</connections>
+<tabstops>
+ <tabstop>fArchive</tabstop>
+ <tabstop>tabWidget</tabstop>
+ <tabstop>fOtherPhone</tabstop>
+ <tabstop>fAddress</tabstop>
+ <tabstop>fFax</tabstop>
+</tabstops>
+<layoutdefaults spacing="6" margin="11"/>
+<includes>
+ <include location="global" impldecl="in implementation">kurlrequester.h</include>
+ <include location="global" impldecl="in implementation">klineedit.h</include>
+ <include location="global" impldecl="in implementation">kpushbutton.h</include>
+</includes>
+</UI>
diff --git a/kpilot/conduits/abbrowserconduit/resolutionDialog.cc b/kpilot/conduits/abbrowserconduit/resolutionDialog.cc
new file mode 100644
index 000000000..2749074f8
--- /dev/null
+++ b/kpilot/conduits/abbrowserconduit/resolutionDialog.cc
@@ -0,0 +1,323 @@
+/* resolutionDialog.h KPilot
+**
+** Copyright (C) 2002-2003 by Reinhold Kainhofer
+**
+** See the .cc file for an explanation of what this file is for.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include "options.h"
+
+#include <qtimer.h>
+#include <qlabel.h>
+#include <qpushbutton.h>
+#include <qlistview.h>
+#include <qregexp.h>
+
+#include "resolutionTable.h"
+#include "resolutionDialog_base.h"
+
+#include "resolutionDialog.moc"
+
+/** This class describes the controllers of the conflict resolution ListView,
+ * as well as its child radio buttons. There are two different constructors
+ * for them.
+ * Each controller has three child radio buttons, and if any of them is
+ * activated (stateChange), it sets the text of its parent (which is the
+ * controller, which is an instance of ResolutionCheckListItem, too).
+ **/
+class ResolutionCheckListItem : QCheckListItem {
+public:
+ ResolutionCheckListItem(ResolutionItem*it, ResolutionTable*tb,
+ QListView*parent);
+ ResolutionCheckListItem(QString header, QString text,
+ ResolutionCheckListItem*parent);
+ ~ResolutionCheckListItem() {};
+ virtual void stateChange(bool newstate);
+ virtual void setValue(QString text);
+ virtual void setCaption(QString caption);
+
+protected:
+ void updateText();
+ /* fResItem is only set for the controller */
+ ResolutionItem*fResItem;
+ bool isController;
+ /* The description of the entry, e.g. Backup, PC, Palm for the radio buttons,
+ * of the field name for the controllers
+ */
+ QString fCaption;
+ /* The currrent value of the entry (for controllers this changes with the
+ * selected button */
+ QString fText;
+};
+
+
+ResolutionCheckListItem::ResolutionCheckListItem(ResolutionItem*it,
+ ResolutionTable*tb, QListView*parent) :
+ QCheckListItem(parent, QString::null, QCheckListItem::Controller),
+ fResItem(it),
+ isController(true),
+ fCaption(it?(it->fName):(QString::null)),
+ fText(it?(it->fResolved):(QString::null))
+{
+ FUNCTIONSETUP;
+ if (it && tb)
+ {
+ // If all three texts are identical, there is no need for
+ // resolution so don't show the radio items below
+ bool itemsEqual=true;
+ QString testtext(QString::null);
+ const enum eExistItems its[3]={eExistsPC, eExistsPalm, eExistsBackup};
+ // get a valid text from a valid field, which will serve as the
+ // test text for the comparison
+ for (int i=0; i<3; i++)
+ {
+ if ((testtext.isNull()) && (it->fExistItems & its[i]) )
+ testtext=it->fEntries[i];
+ }
+ for (int i=0; i<3; i++)
+ {
+ if (it->fExistItems & its[i])
+ itemsEqual&=(it->fEntries[i]==testtext);
+ }
+ if (!itemsEqual)
+ {
+ ResolutionCheckListItem*item;
+ for (int i=2; i>=0; i--)
+ {
+ // Add only existing items
+ if (it->fExistItems & its[i])
+ {
+ item=new ResolutionCheckListItem(it->fEntries[i], tb->labels[i], this);
+ item->setOn(it->fEntries[i]==fText);
+ }
+ }
+ }
+ updateText();
+ }
+ setOpen(true);
+}
+
+ResolutionCheckListItem::ResolutionCheckListItem(QString text, QString header,
+ ResolutionCheckListItem*parent) :
+ QCheckListItem(parent, QString(), QCheckListItem::RadioButton),
+ fResItem(0L),
+ isController(false),
+ fCaption(header),
+ fText(text)
+{
+ updateText();
+}
+
+void ResolutionCheckListItem::stateChange(bool newstate)
+{
+ if (newstate && !isController)
+ {
+ ResolutionCheckListItem*par=static_cast<ResolutionCheckListItem*>(parent());
+ {
+ par->setValue(fText);
+ }
+ }
+}
+
+void ResolutionCheckListItem::setValue(QString text)
+{
+ FUNCTIONSETUP;
+ fText=text;
+ if (isController && fResItem)
+ {
+ fResItem->fResolved=text;
+ }
+ updateText();
+}
+
+void ResolutionCheckListItem::setCaption(QString caption)
+{
+ fCaption=caption;
+ updateText();
+}
+
+void ResolutionCheckListItem::updateText()
+{
+ QString newText(i18n("Entries in the resolution dialog. First the name of the field, then the entry from the Handheld or PC after the colon", "%1: %2").arg(fCaption).arg(fText));
+ newText.replace(QRegExp(CSL1("\n")),
+ i18n("Denoting newlines in Address entries. No need to translate", " | "));
+ setText(0, newText);
+}
+
+
+
+/*****************************************************************
+ *
+ *****************************************************************/
+
+ResolutionDlg::ResolutionDlg( QWidget* parent, KPilotLink*fH,
+ const QString &caption, const QString &helpText, ResolutionTable*tab) :
+ KDialogBase( parent, "ResolutionDlg", false, caption, Apply|Cancel, Apply),
+ tickleTimer(0L),
+ fHandle(fH),
+ fTable(tab)
+{
+ fWidget = new ResolutionDialogBase( this );
+ setMainWidget(fWidget);
+ fTable->fResolution=SyncAction::eDoNothing;
+ fWidget->fIntroText->setText(helpText);
+
+ fillListView();
+ adjustButtons(tab);
+
+ adjustSize();
+ resize(size());
+
+ if (fHandle) tickleTimer=new QTimer(this, "TickleTimer");
+
+ if (tickleTimer)
+ {
+ connect( tickleTimer, SIGNAL(timeout()), this, SLOT(_tickle()));
+ // tickle the palm every 10 seconds to prevent a timeout until the
+ // sync is really finished.
+ tickleTimer->start( 10000 );
+ }
+
+ connect(fWidget->fKeepBoth, SIGNAL(clicked()), SLOT(slotKeepBoth()));
+ connect(fWidget->fBackupValues, SIGNAL(clicked()), SLOT(slotUseBackup()));
+ connect(fWidget->fPalmValues, SIGNAL(clicked()), SLOT(slotUsePalm()));
+ connect(fWidget->fPCValues, SIGNAL(clicked()), SLOT(slotUsePC()));
+}
+
+void ResolutionDlg::adjustButtons(ResolutionTable*tab)
+{
+ FUNCTIONSETUP;
+ if (!tab) return;
+ if (!(tab->fExistItems & eExistsPC) )
+ {
+ fWidget->fPCValues->setText(i18n("Delete entry"));
+ fWidget->fKeepBoth->setDisabled(TRUE);
+ fWidget->fKeepBoth->hide();
+ }
+ if (!(tab->fExistItems & eExistsPalm) )
+ {
+ fWidget->fPalmValues->setText(i18n("Delete entry"));
+ fWidget->fKeepBoth->setDisabled(TRUE);
+ fWidget->fKeepBoth->hide();
+ }
+ if (!(tab->fExistItems & eExistsBackup) )
+ {
+ fWidget->fBackupValues->setDisabled(TRUE);
+ }
+}
+
+void ResolutionDlg::fillListView()
+{
+ FUNCTIONSETUP;
+ fWidget->fResolutionView->setSorting(-1, FALSE);
+ fWidget->fResolutionView->clear();
+ for ( ResolutionItem* it = fTable->last(); it; it = fTable->prev() )
+ {
+#ifdef DEBUG
+ DEBUGKPILOT<<"Building table, items="<<it->fExistItems<<", PC="<<
+ it->fEntries[0]<<", Palm="<<it->fEntries[1]<<", Backup="<<
+ it->fEntries[2]<<endl;
+#endif
+ bool hasValidValues=false;
+ if (it->fExistItems & eExistsPC)
+ hasValidValues = hasValidValues || !(it->fEntries[0].isEmpty());
+ if (it->fExistItems & eExistsPalm)
+ hasValidValues = hasValidValues || !(it->fEntries[1].isEmpty());
+ if (it->fExistItems & eExistsBackup)
+ hasValidValues = hasValidValues || !(it->fEntries[2].isEmpty());
+ if (hasValidValues)
+ new ResolutionCheckListItem(it, fTable, fWidget->fResolutionView);
+ }
+}
+
+void ResolutionDlg::slotKeepBoth()
+{
+ if ( (fTable->fExistItems & eExistsPC) && (fTable->fExistItems & eExistsPalm) )
+ {
+ fTable->fResolution=SyncAction::eDuplicate;
+ }
+ else
+ {
+ fTable->fResolution=SyncAction::eDoNothing;
+ }
+ done(fTable->fResolution);
+}
+
+void ResolutionDlg::slotUseBackup()
+{
+ if (fTable->fExistItems & eExistsBackup)
+ {
+ fTable->fResolution=SyncAction::ePreviousSyncOverrides;
+ }
+ else
+ {
+ fTable->fResolution=SyncAction::eDoNothing;
+ }
+ done(fTable->fResolution);
+}
+
+void ResolutionDlg::slotUsePalm()
+{
+ if (fTable->fExistItems & eExistsPalm)
+ {
+ fTable->fResolution=SyncAction::eHHOverrides;
+ }
+ else
+ {
+ fTable->fResolution=SyncAction::eDelete;
+ }
+ done(fTable->fResolution);
+}
+
+void ResolutionDlg::slotUsePC()
+{
+ if (fTable->fExistItems & eExistsPC)
+ {
+ fTable->fResolution=SyncAction::ePCOverrides;
+ }
+ else
+ {
+ fTable->fResolution=SyncAction::eDelete;
+ }
+ done(fTable->fResolution);
+}
+
+void ResolutionDlg::slotApply()
+{
+ fTable->fResolution=SyncAction::eAskUser;
+ done(fTable->fResolution);
+}
+
+void ResolutionDlg::_tickle()
+{
+ if (fHandle) fHandle->tickle();
+}
+
+/*
+ * Destroys the object and frees any allocated resources
+ */
+ResolutionDlg::~ResolutionDlg()
+{
+ // no need to delete child widgets, Qt does it all for us
+}
diff --git a/kpilot/conduits/abbrowserconduit/resolutionDialog.h b/kpilot/conduits/abbrowserconduit/resolutionDialog.h
new file mode 100644
index 000000000..5f41ba0f2
--- /dev/null
+++ b/kpilot/conduits/abbrowserconduit/resolutionDialog.h
@@ -0,0 +1,70 @@
+#ifndef RESOLUTIONDIALOG_H
+#define RESOLUTIONDIALOG_H
+/* resolutionDialog.h KPilot
+**
+** Copyright (C) 2002-2003 by Reinhold Kainhofer
+**
+** See the .cc file for an explanation of what this file is for.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include <kdialogbase.h>
+class KPilotLink;
+class QTimer;
+class QListView;
+class ResolutionDialogBase;
+
+
+class ResolutionTable;
+
+class ResolutionDlg : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+ ResolutionDlg( QWidget* parent=0,
+ KPilotLink*fH=0L,
+ const QString &caption=QString(),
+ const QString &helpText=QString(),
+ ResolutionTable *tab=0L );
+ ~ResolutionDlg();
+
+public slots:
+ void slotKeepBoth();
+ void slotUseBackup();
+ void slotUsePalm();
+ void slotUsePC();
+ void slotApply();
+ void _tickle();
+protected:
+ void fillListView();
+ void adjustButtons(ResolutionTable*tab);
+
+ QTimer* tickleTimer;
+ KPilotLink* fHandle;
+ ResolutionTable*fTable;
+
+ ResolutionDialogBase*fWidget;
+};
+
+#endif // RESOLUTIONDIALOG_H
diff --git a/kpilot/conduits/abbrowserconduit/resolutionDialog_base.ui b/kpilot/conduits/abbrowserconduit/resolutionDialog_base.ui
new file mode 100644
index 000000000..38fa73e89
--- /dev/null
+++ b/kpilot/conduits/abbrowserconduit/resolutionDialog_base.ui
@@ -0,0 +1,129 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>ResolutionDialogBase</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>widget2</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>459</width>
+ <height>350</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>widget2</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>fIntroText</cstring>
+ </property>
+ <property name="text">
+ <string>The following record was edited both on the handheld and on the PC. Please choose which values shall be synced:</string>
+ </property>
+ <property name="alignment">
+ <set>WordBreak|AlignVCenter</set>
+ </property>
+ </widget>
+ <widget class="QListView" row="1" column="0">
+ <column>
+ <property name="text">
+ <string>Field</string>
+ </property>
+ <property name="clickable">
+ <bool>false</bool>
+ </property>
+ <property name="resizable">
+ <bool>false</bool>
+ </property>
+ </column>
+ <property name="name">
+ <cstring>fResolutionView</cstring>
+ </property>
+ <property name="rootIsDecorated">
+ <bool>true</bool>
+ </property>
+ <property name="resizeMode">
+ <enum>AllColumns</enum>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Use this list to resolve, field by field, the conflicts created when a record was edited both on the handheld and on the PC. For each record, the different values from the last sync, the handheld and PC are displayed for each field, allowing you to choose the desired value.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="2" column="0">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Line breaks in any of the entries are denoted by a " | " (without the quotes).</string>
+ </property>
+ <property name="alignment">
+ <set>WordBreak|AlignVCenter</set>
+ </property>
+ </widget>
+ <widget class="QFrame" row="3" column="0">
+ <property name="name">
+ <cstring>frame3</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>GroupBoxPanel</enum>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QPushButton" row="0" column="1">
+ <property name="name">
+ <cstring>fKeepBoth</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Keep Both</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Click this button to use both values, resulting in the duplication of the record.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="0" column="0">
+ <property name="name">
+ <cstring>fPCValues</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;PC Values</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Click this button to use the PC values for synchronizing all conflicting fields in this record.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="1" column="0">
+ <property name="name">
+ <cstring>fBackupValues</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Last Sync Values</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Click this button to use the last sync values (old values) for synchronizing all conflicting fields in this record.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="1" column="1">
+ <property name="name">
+ <cstring>fPalmValues</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Handheld Values</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Click this button to use the handheld values for synchronizing all conflicting fields in this record.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </grid>
+</widget>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/kpilot/conduits/abbrowserconduit/resolutionTable.h b/kpilot/conduits/abbrowserconduit/resolutionTable.h
new file mode 100644
index 000000000..760f962e2
--- /dev/null
+++ b/kpilot/conduits/abbrowserconduit/resolutionTable.h
@@ -0,0 +1,70 @@
+#ifndef RESOLUTIONTABLE_H
+#define RESOLUTIONTABLE_H
+/* resolutionTable.h KPilot
+**
+** Copyright (C) 2003 by Reinhold Kainhofer
+**
+** See the .cc file for an explanation of what this file is for.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+
+#include <qvaluelist.h>
+#include "syncAction.h"
+
+typedef enum eExistItems {
+ eExistsPC=0x1, eExistsPalm=0x2, eExistsBackup=0x4,
+ eExistsAll=eExistsPC|eExistsPalm|eExistsBackup
+};
+
+class ResolutionItem
+{
+public:
+ enum eExistItems fExistItems;
+ QString fEntries[3];
+ QString fResolved;
+ QString fName;
+public:
+ ResolutionItem() {}
+ ResolutionItem(QString name, int ex, QString pc, QString palm, QString backup):fExistItems((eExistItems)ex),fName(name)
+ {fEntries[0]=pc;fEntries[1]=palm; fEntries[2]=backup; /*fExistItems=(eExistItems)ex;*/ }
+ ~ResolutionItem() {}
+};
+
+/**
+@author Reinhold Kainhofer
+*/
+class ResolutionTable : public QPtrList<ResolutionItem>
+{
+public:
+ ResolutionTable():QPtrList<ResolutionItem>() {fResolution=SyncAction::eAskUser;};
+
+ ~ResolutionTable() {};
+
+ SyncAction::ConflictResolution fResolution;
+ QString labels[3];
+ enum eExistItems fExistItems;
+};
+
+#endif
+
diff --git a/kpilot/conduits/configure.in.bot b/kpilot/conduits/configure.in.bot
new file mode 100644
index 000000000..688f775f9
--- /dev/null
+++ b/kpilot/conduits/configure.in.bot
@@ -0,0 +1,14 @@
+dnl Configure.in.bot for KPilot conduits.
+dnl
+dnl Copyright (C) 2000,2001 Adriaan de Groot
+dnl Copyright (C) 2002 Reinhold Kainhofer
+dnl
+dnl This file is released under the terms of the Gnu General Public
+dnl Licence (GPL) Version 2.
+
+if test "$with_mal" = NOTFOUND -o "$with_mal" = no ; then
+ echo ""
+ echo "KPILOT: MAL headers or library not found. AvantGo conduit will not be compiled."
+ echo "KPILOT: Download libmal>=0.20 from http://jasonday.home.att.net/code/libmal/"
+ echo ""
+fi
diff --git a/kpilot/conduits/configure.in.in b/kpilot/conduits/configure.in.in
new file mode 100644
index 000000000..c6a0d1437
--- /dev/null
+++ b/kpilot/conduits/configure.in.in
@@ -0,0 +1,241 @@
+dnl Configure.in.in for KPilot conduits.
+dnl
+dnl Copyright (C) 2000,2001 Adriaan de Groot
+dnl Copyright (C) 2002 Reinhold Kainhofer
+dnl
+dnl This file is released under the terms of the Gnu General Public
+dnl Licence (GPL) Version 2.
+
+
+
+
+dnl ----------------------------------------------------------------------------
+dnl
+dnl checks for the MAL conduit
+dnl
+dnl ----------------------------------------------------------------------------
+
+dnl
+dnl
+dnl Check to see if MAL header and library are available
+dnl
+
+dnl
+dnl Questions and comments can be sent to kde-pim@kde.org
+dnl
+dnl This was copied and adapted from kabc's ldap configure.in.in
+
+
+AC_DEFUN([KPILOT_CHECK_MAL],
+[
+AC_REQUIRE([KDE_CHECK_LIB64])
+AC_REQUIRE([KPILOT_CHECK_PISOCK])
+
+AC_MSG_CHECKING(for libmal (for KPilots MAL conduit))
+AC_ARG_WITH(mal,
+[ --with-mal=PATH set path for libmal files @<:@default=check@:>@],
+[ case "$withval" in
+ yes)
+ with_mal=CHECK
+ ;;
+ esac ],
+[ with_mal=CHECK ]
+)dnl
+
+if test "x$with_mal" = "xCHECK" ; then
+ with_mal=NOTFOUND
+ search_incs_tmp="$kde_includes /usr/include /usr/local/include"
+ dnl build the list of include dirs, both with and without libmal appended
+ search_incs="";
+ for idir in $search_incs_tmp; do
+ search_incs="$search_incs $idir $idir/libmal"
+ done
+ AC_FIND_FILE(libmal.h, $search_incs, mal_incdir)
+ if test -r $mal_incdir/libmal.h ; then
+ test "x$mal_incdir" != "x/usr/include" && MAL_INCLUDE="-I$mal_incdir"
+ with_mal=FOUND
+ fi
+ if test $with_mal = FOUND ; then
+ with_mal=NOTFOUND
+ for ext in la so sl a ; do
+ AC_FIND_FILE(libmal.$ext, $kde_libraries $libdir /usr/lib$kdelibsuff /usr/local/lib$kdelibsuff $libdir/libmal /usr/lib/libmal /usr/local/lib/libmal,
+ mal_libdir)
+ if test -r $mal_libdir/libmal.$ext ; then
+ if test "x$mal_libdir" != "x/usr/lib$kdelibsuff" ; then
+ MAL_LIB="-L$mal_libdir "
+ test "$USE_RPATH" = yes && MAL_RPATH="-R $mal_libdir"
+ fi
+ MAL_LIB="${MAL_LIB}-lmal"
+ with_mal=FOUND
+ break
+ fi
+ done
+ fi
+fi
+
+case "$with_mal" in
+no) AC_MSG_RESULT(no) ;;
+NOTFOUND) AC_MSG_RESULT(searched but not found) ;;
+*)
+ if test "x$with_mal" = "xFOUND" ; then
+ msg="incs=$mal_incdir libs=$mal_libdir"
+ else
+ msg="$with_mal"
+ MAL_ROOT="$with_mal"
+ if test "x$MAL_ROOT" != "x/usr" ; then
+ MAL_INCLUDE="-I${MAL_ROOT}/include"
+ MAL_LIB="-L${MAL_ROOT}/lib$kdelibsuff "
+ if test "$USE_RPATH" = "yes" ; then
+ MAL_RPATH="-R ${MAL_ROOT}/lib$kdelibsuff"
+ fi
+ fi
+ MAL_LIB="${MAL_LIBS}-lmal"
+ fi
+
+ kde_save_LIBS="$LIBS"
+ kde_save_CFLAGS="$CFLAGS"
+ kde_save_CPPFLAGS="$CPPFLAGS"
+ kde_save_LDFLAGS="$LDFLAGS"
+ LIBS="$LIBS $PISOCK_LIB $MAL_LIB"
+ CFLAGS="$CFLAGS $MAL_INCLUDE"
+ CPPFLAGS="$CPPFLAGS $all_includes $PISOCK_INCLUDE $MAL_INCLUDE"
+ LDFLAGS="$LDFLAGS $PISOCK_LDFLAGS $all_libraries"
+ AC_LANG_SAVE
+ AC_LANG_CPLUSPLUS
+ AC_TRY_LINK(dnl
+ [
+ #include <libmal.h>
+ ],
+ [
+ PalmSyncInfo *psi;
+ ],
+ , with_mal=no
+ )
+ if test "$with_mal" = "no" ; then
+ MAL_LIB="$MAL_LIB -ldl"
+ LIBS="$LIBS $PISOCK_LIB $MAL_LIB"
+ with_mal=yes
+ AC_TRY_LINK(dnl
+ [
+ #include <libmal.h>
+ ],
+ [
+ PalmSyncInfo *psi;
+ ],
+ , with_mal=no
+ )
+ fi
+ if test "$with_mal" = "no" ; then
+ MAL_INCLUDE=
+ MAL_LIB=
+ MAL_RPATH=
+ AC_MSG_RESULT(no (but first try gave $msg))
+ else
+ AC_DEFINE(HAVE_LIBMAL, 1, [Define if you have MAL libraries])
+ dnl check which version we have (pre 0.40 or >=0.40):
+ AC_TRY_LINK(dnl
+ [#include <libmal.h>],
+ [
+ PalmSyncInfo *psi;
+ psi->httpProxy;
+ ],
+ , mal_version20=yes
+ )
+ if test "$mal_version20" = "yes" ; then
+ AC_DEFINE(LIBMAL20, 1, [Define if we have the old libmal version (<0.40)])
+ fi
+ HAVE_LIBMAL=1
+ AC_MSG_RESULT($msg)
+ fi
+ AC_LANG_RESTORE
+ CFLAGS=$kde_save_CFLAGS
+ CPPFLAGS=$kde_save_CPPFLAGS
+ LIBS=$kde_save_LIBS
+ LDFLAGS=$kde_save_LDFLAGS
+ ;;
+esac
+
+AC_SUBST(MAL_INCLUDE)
+AC_SUBST(MAL_LIB)
+AC_SUBST(MAL_RPATH)
+
+AM_CONDITIONAL(include_malconduit, test "$HAVE_LIBMAL" = 1)
+
+])
+
+dnl ----------------------------------------------------------------------------
+dnl
+dnl checks for the addressbook conduit
+dnl
+dnl ----------------------------------------------------------------------------
+
+AC_DEFUN([KPILOT_CHECK_KABC],[HAVE_KABC=0
+KDE_CHECK_HEADER(kresources/factory.h,HAVE_KABC=1,
+ AC_MSG_WARN([KPILOT: Older kaddressbook version detected. No address book
+ conduit will be compiled.]))
+AM_CONDITIONAL(include_abc, test "$HAVE_KABC" = 1)
+])
+
+dnl ----------------------------------------------------------------------------
+dnl
+dnl checks for the notepad conduit
+dnl
+dnl ----------------------------------------------------------------------------
+
+AC_DEFUN([KPILOT_CHECK_NOTEPAD],[HAVE_NOTEPAD=0
+kpilot_save_cflags="$CPPFLAGS"
+kpilot_save_ldflags="$LDFLAGS"
+
+test -z "$PISOCK_INCLUDE" || CPPFLAGS="$CPPFLAGS $PISOCK_INCLUDE"
+KDE_CHECK_HEADER(pi-notepad.h,HAVE_NOTEPAD=1,
+ AC_MSG_WARN([KPILOT: No notepad.h for pilot-link. Your pilot-link is too old.]))
+
+CPPFLAGS="$kpilot_save_cflags"
+LDFLAGS="$kpilot_save_ldflags"
+unset kpilot_save_cflags
+unset kpilot_save_ldflags
+
+AM_CONDITIONAL(include_notepad, test "$HAVE_NOTEPAD" = 1)
+])
+
+dnl ----------------------------------------------------------------------------
+dnl
+dnl checks for embedded language conduits
+dnl
+dnl ----------------------------------------------------------------------------
+
+AC_DEFUN([KPILOT_CHECK_PERL],[HAVE_PERL=0
+AC_MSG_CHECKING([for Perl embedding])
+if perl -MExtUtils::Embed -e ccopts > /dev/null 2> /dev/null ; then
+ PERL_CFLAGS=`perl -MExtUtils::Embed -e ccopts 2> /dev/null`
+ PERL_LDFLAGS=`perl -MExtUtils::Embed -e ldopts 2> /dev/null`
+ HAVE_PERL=1
+ AC_MSG_RESULT(yes)
+else
+ PERL_CFLAGS=""
+ PERL_LDFLAGS=""
+ AC_MSG_RESULT(no)
+fi
+AC_SUBST(PERL_CFLAGS)
+AC_SUBST(PERL_LDFLAGS)
+AM_CONDITIONAL(include_perl, test "$HAVE_PERL" = 1)
+])
+
+AC_DEFUN([KPILOT_CHECK_PYTHON],[HAVE_PYTHON=0
+AC_MSG_CHECKING([for Python embedding])
+AM_CONDITIONAL(include_python, test "$HAVE_PYTHON" = 1)
+AC_MSG_RESULT(N/A)
+])
+
+dnl ----------------------------------------------------------------------------
+dnl
+dnl actually call the checks
+dnl
+dnl ----------------------------------------------------------------------------
+
+KPILOT_CHECK_MAL
+KPILOT_CHECK_KABC
+KPILOT_CHECK_PERL
+KPILOT_CHECK_PYTHON
+KPILOT_CHECK_NOTEPAD
+
diff --git a/kpilot/conduits/docconduit/CMakeLists.txt b/kpilot/conduits/docconduit/CMakeLists.txt
new file mode 100644
index 000000000..fa87eb0fb
--- /dev/null
+++ b/kpilot/conduits/docconduit/CMakeLists.txt
@@ -0,0 +1,87 @@
+include_directories(
+ ${CMAKE_CURRENT_BINARY_DIR}
+)
+
+set(doc_shared_SRCS
+ makedoc9.cc
+ pilotDOCHead.cc
+ pilotDOCEntry.cc
+ pilotDOCBookmark.cc
+ DOC-converter.cc
+)
+
+set(conduit_doc_SRCS
+ ${doc_shared_SRCS}
+ kpalmdoc_dlg.cc
+ kpalmdoc.cpp
+ doc-factory.cc
+ doc-setup.cc
+ doc-conduit.cc
+ doc-conflictdialog.cc
+)
+
+set(conduit_doc_UIS
+ kpalmdoc_dlgbase.ui
+ doc-setupdialog.ui
+)
+
+set(conduit_doc_KCFGS
+ docconduitSettings.kcfgc
+ kpalmdocSettings.kcfgc
+)
+
+kde3_add_kcfg_files(conduit_doc_SRCS ${conduit_doc_KCFGS})
+kde3_add_ui_files(conduit_doc_SRCS ${conduit_doc_UIS})
+kde3_automoc(${conduit_doc_SRCS})
+add_library(conduit_doc SHARED ${conduit_doc_SRCS})
+
+kpilot_rpath(conduit_doc)
+
+set_target_properties(
+ conduit_doc PROPERTIES LOCATION ${KDE3_PLUGIN_INSTALL_DIR}
+ PREFIX ""
+)
+
+kde3_install_libtool_file(conduit_doc)
+
+install(
+ TARGETS conduit_doc
+ LIBRARY DESTINATION ${KDE3_PLUGIN_INSTALL_DIR}
+)
+
+set(kpalmdoc_SRCS
+ ${doc_shared_SRCS}
+ kpalmdoc_dlg.cc
+ kpalmdoc.cpp
+)
+kde3_add_kcfg_files(kpalmdoc_SRCS kpalmdocSettings.kcfgc)
+kde3_add_ui_files(kpalmdoc_SRCS kpalmdoc_dlgbase.ui)
+kde3_automoc(${kpalmdoc_SRCS})
+add_executable(kpalmdoc ${kpalmdoc_SRCS})
+target_link_libraries(kpalmdoc ${QT_LIBRARIES} kpilot kdeui kio)
+kpilot_rpath(kpalmdoc)
+
+install(
+ TARGETS kpalmdoc conduit_doc
+ LIBRARY DESTINATION ${KDE3_PLUGIN_INSTALL_DIR}
+ RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin
+)
+
+install(
+ FILES doc_conduit.desktop DESTINATION ${KDE3_SERVICES_DIR}
+)
+
+install(
+ FILES docconduit.kcfg kpalmdoc.kcfg DESTINATION ${KDE3_KCFG_DIR}
+)
+
+install(
+ FILES kpalmdoc.desktop DESTINATION ${KDE3_XDG_APPS_DIR}
+)
+
+install(
+ FILES kpalmdoc.upd
+ DESTINATION ${CMAKE_INSTALL_PREFIX}/share/apps/kconf_update
+)
+
+add_subdirectory(Icons)
diff --git a/kpilot/conduits/docconduit/DOC-converter.cc b/kpilot/conduits/docconduit/DOC-converter.cc
new file mode 100644
index 000000000..c8d7ac02d
--- /dev/null
+++ b/kpilot/conduits/docconduit/DOC-converter.cc
@@ -0,0 +1,631 @@
+/* KPilot
+**
+** Copyright (C) 2002-2003 by Reinhold Kainhofer
+**
+** The doc converter synchronizes text files on the PC with DOC databases on the Palm
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+
+#include "options.h"
+#include "DOC-converter.moc"
+
+#include <qdir.h>
+#include <qfileinfo.h>
+#include <qregexp.h>
+#include <qsortedlist.h>
+
+#include <pilotDatabase.h>
+#include <pilotLocalDatabase.h>
+#include <pilotSerialDatabase.h>
+
+#include "pilotDOCHead.h"
+#include "pilotDOCEntry.h"
+#include "pilotDOCBookmark.h"
+
+
+
+#define min(a,b) (a<b)?(a):(b)
+
+
+
+/****************************************************************************************************
+ * various bookmark classes. Most important is the bmkList findMatches(QString) function,
+ * which needs to return a list of all bookmarks found for the given bookmark expression.
+ * A bookmark usually consists of a bookmark text and an offset into the text document.
+ ****************************************************************************************************/
+
+
+bool docBookmark::compare_pos=true;
+
+bool operator< ( const docBookmark &s1, const docBookmark &s2)
+{
+ if (docBookmark::compare_pos) { return s1.position<s2.position;}
+ else {return s2.bmkName<s2.bmkName;}
+}
+
+bool operator== ( const docBookmark &s1, const docBookmark &s2)
+{
+ return (s1.position==s2.position) && (s1.bmkName==s2.bmkName);
+}
+
+
+int docMatchBookmark::findMatches(QString doctext, bmkList &fBookmarks) {
+ FUNCTIONSETUP;
+// bmkList res;
+ int pos = 0, nr=0, found=0;
+#ifdef DEBUG
+ DEBUGKPILOT<<"Finding matches of "<<pattern<<endl;
+#endif
+
+ while (pos >= 0 && found<to) {
+ pos = doctext.find(pattern, pos);
+#ifdef DEBUG
+ DEBUGKPILOT<<"Result of search: pos="<<pos<<endl;
+#endif
+ if (pos >= 0)
+ {
+ ++found;
+ if (found>=from && found<=to) {
+ fBookmarks.append(new docBookmark(pattern, pos));
+ ++nr;
+
+ }
+ ++pos;
+ }
+ }
+ return nr;
+}
+
+
+
+int docRegExpBookmark::findMatches(QString doctext, bmkList &fBookmarks)
+{
+ FUNCTIONSETUP;
+// bmkList res;
+ QRegExp rx(pattern);
+ int pos = 0, nr=0, found=0;
+
+ while (pos>=0 && found<=to) {
+#ifdef DEBUG
+ DEBUGKPILOT<<"Searching for bookmark "<<pattern<<endl;
+#endif
+ pos=rx.search(doctext, pos);
+ if (pos > -1) {
+ ++found;
+ if (found>=from && found<to) {
+ if (capSubexpression>=0) {
+ fBookmarks.append(new docBookmark(/*bmkName.left(16)*/rx.cap(capSubexpression), pos));
+ } else {
+ // TODO: use the subexpressions from the regexp for the bmk name ($1..$9) (given as separate regexp)
+ QString bmkText(bmkName);
+ for (int i=0; i<=rx.numCaptures(); ++i) {
+ bmkText.replace(CSL1("$%1").arg(i), rx.cap(i));
+ bmkText.replace(CSL1("\\%1").arg(i), rx.cap(i));
+ }
+ fBookmarks.append(new docBookmark(bmkText.left(16), pos));
+ }
+ ++nr;
+ }
+ ++pos;
+ }
+ }
+ return nr;
+}
+
+
+
+
+
+
+
+
+/*********************************************************************
+ C O N S T R U C T O R
+ *********************************************************************/
+
+
+DOCConverter::DOCConverter(QObject *parent, const char *name):QObject(parent,name) {
+ FUNCTIONSETUP;
+ docdb=0L;
+ eSortBookmarks=eSortNone;
+ fBookmarks.setAutoDelete( TRUE );
+}
+
+
+
+DOCConverter::~DOCConverter() {
+ FUNCTIONSETUP;
+}
+
+
+
+
+
+/*********************************************************************
+ S Y N C S T R U C T U R E
+ *********************************************************************/
+
+
+
+void DOCConverter::setTXTpath(QString path, QString file) {
+ QDir dr(path);
+ QFileInfo pth(dr, file);
+ if (!file.isEmpty())
+ txtfilename = pth.absFilePath();
+}
+
+
+
+void DOCConverter::setTXTpath(QString filename) {
+ if (!filename.isEmpty()) txtfilename = filename;
+}
+
+
+
+void DOCConverter::setPDB(PilotDatabase * dbi) {
+ if (dbi) docdb = dbi;
+}
+
+
+
+QString DOCConverter::readText() {
+ FUNCTIONSETUP;
+ if (txtfilename.isEmpty()) return QString();
+ QFile docfile(txtfilename);
+ if (!docfile.open(IO_ReadOnly))
+ {
+ emit logError(i18n("Unable to open text file %1 for reading.").arg(txtfilename));
+ return QString();
+ }
+
+ QTextStream docstream(&docfile);
+
+ QString doc = docstream.read();
+ docfile.close();
+ return doc;
+}
+
+
+
+int DOCConverter::findBmkEndtags(QString &text, bmkList&fBmks) {
+ FUNCTIONSETUP;
+ // Start from the end of the text
+ int pos = text.length() - 1, nr=0;
+ bool doSearch=true;
+ while (pos >= 0/* && doSearch*/) {
+ DEBUGKPILOT<<"Current character is \'"<<text[pos].latin1()<<"\'"<<endl;
+ // skip whitespace until we reach a >
+ while (text[pos].isSpace() && pos >= 0) {
+ DEBUGKPILOT<<"Skipping whitespaces at the end of the file"<<endl;
+ pos--;
+ }
+ // every other character than a > is assumed to belong to the text, so there are no more bookmarks.
+ if (pos < 0 || text[pos] != '>') {
+ DEBUGKPILOT<<"Current character \'"<<text[pos].latin1()<<"\' at position "<<pos<<" is not and ending >. Finish searching for bookmarks."<<endl;
+
+ pos=-1;
+ break;
+ } else {
+ int endpos = pos;
+ doSearch=true;
+ DEBUGKPILOT<<"Found the ending >, now looking for the opening <"<<endl;
+
+ // Search for the opening <. There must not be a newline in the bookmark text.
+ while (doSearch && pos > 0) {
+// DEBUGKPILOT<<"pos="<<pos<<", char="<<text[pos].latin1()<<endl;
+ pos--;
+ if (text[pos] == '\n') {
+ DEBUGKPILOT<<"Found carriage return at position "<<pos<<" inside the bookmark text, assuming this is not a bookmark, and the text ends in a >"<<endl;
+ doSearch = false;
+ pos = -1;
+ break;
+ }
+ if (text[pos] == '<') {
+ fBmks.append(new docMatchBookmark(text.mid(pos + 1, endpos - pos - 1)));
+ ++nr;
+ DEBUGKPILOT<<"Found opening < at position "<<pos<<", bookmarktext ="<<text.mid(pos+1, endpos-pos-1)<<endl;
+ text.remove(pos, text.length());
+ pos--;
+ doSearch = false;
+ }
+ }
+ }
+ DEBUGKPILOT<<"Finished processing the next bookmark, current position: "<<pos<<endl;
+ }
+ return nr;
+}
+
+int DOCConverter::findBmkInline(QString &text, bmkList &fBmks) {
+ FUNCTIONSETUP;
+// bmkList res;
+ int nr=0;
+ QRegExp rx(CSL1("<\\*(.*)\\*>"));
+
+ rx.setMinimal(TRUE);
+ int pos = 0;
+ while (pos >= 0) {
+ pos = rx.search(text, pos);
+ if (pos >= 0) {
+ fBmks.append(new docBookmark(rx.cap(1), pos+1));
+ ++nr;
+ text = text.remove(pos, rx.matchedLength());
+ }
+ }
+ return nr;
+}
+
+int DOCConverter::findBmkFile(QString &, bmkList &fBmks) {
+ FUNCTIONSETUP;
+ int nr=0;
+
+ QString bmkfilename = txtfilename;
+ if (bmkfilename.endsWith(CSL1(".txt"))){
+ bmkfilename.remove(bmkfilename.length()-4, 4);
+ }
+ QString oldbmkfilename=bmkfilename;
+ bmkfilename+=CSL1(BMK_SUFFIX);
+ QFile bmkfile(bmkfilename);
+ if (!bmkfile.open(IO_ReadOnly)) {
+ bmkfilename=oldbmkfilename+CSL1(PDBBMK_SUFFIX);
+ bmkfile.setName(bmkfilename);
+ if (!bmkfile.open(IO_ReadOnly)) {
+ DEBUGKPILOT<<"Unable to open bookmarks file "<<bmkfilename<<" for reading the bookmarks of "<<docdb ->dbPathName()<<endl;
+ return 0;
+ }
+ }
+
+ DEBUGKPILOT<<"Bookmark file: "<<bmkfilename<<endl;
+
+ QTextStream bmkstream(&bmkfile);
+ QString line;
+ while ( !(line=bmkstream.readLine()).isEmpty() ) {
+ if (!line.isEmpty() && !line.startsWith(CSL1("#")) ) {
+ QStringList bmkinfo=QStringList::split(CSL1(","), line);
+ int fieldnr=bmkinfo.count();
+ // We use the same syntax for the entries as MakeDocJ bookmark files:
+ // <bookmark>,<string-to-search>,<bookmark-name-string>,<starting-bookmark>,<ending-bookmark>
+ // For an explanation see: http://home.kc.rr.com/krzysztow/PalmPilot/MakeDocJ/index.html
+ if (fieldnr>0){
+ DEBUGKPILOT<<"Working on bookmark \""<<line<<"\""<<endl;
+ docMatchBookmark*bmk=0L;
+ QString bookmark=bmkinfo[0];
+ bool ok;
+ int pos=bookmark.toInt(&ok);
+ if (ok) {
+ if (fieldnr>1) {
+ QString name(bmkinfo[1]);
+ DEBUGKPILOT<<"Bookmark \""<<name<<"\" set at position "<<pos<<endl;
+ fBmks.append(new docBookmark(name, pos));
+ }
+ } else if (bookmark==CSL1("-") || bookmark==CSL1("+")) {
+ if (fieldnr>1) {
+ QString patt(bmkinfo[1]);
+ QString name(patt);
+ if (fieldnr>2) {
+ int cap=bmkinfo[2].toInt(&ok);
+ if (ok) {
+ bmk=new docRegExpBookmark(patt, cap);
+ } else {
+ name=bmkinfo[2];
+ bmk=new docRegExpBookmark(patt, name);
+ }
+ } else{
+ bmk=new docRegExpBookmark(patt, name);
+ }
+ // The third entry in the line (optional) denotes the index of a capture subexpression (if an integer) or the bookmark text as regexp (if a string)
+ DEBUGKPILOT<<"RegExp Bookmark, pattern="<<patt<<", name="<<name<<endl;
+ if (bmk) {
+ if (bookmark==CSL1("-")) {
+ bmk->from=1;
+ bmk->to=1;
+ } else {
+ if (fieldnr>3) {
+ bool ok;
+ int tmp=bmkinfo[3].toInt(&ok);
+ if (ok) bmk->from=tmp;
+ if (fieldnr>4) {
+ tmp=bmkinfo[4].toInt(&ok);
+ if (ok) bmk->to=tmp;
+ }
+ }
+ }
+ fBmks.append(bmk);
+ bmk=0L;
+ } else {
+ DEBUGKPILOT<<"Could not allocate bookmark "<<name<<endl;
+ }
+ } else {
+ DEBUGKPILOT<<"RegExp bookmark found with no other information (no bookmark pattern nor name)"<<endl;
+ }
+ } else {
+ QString pattern(bookmark);
+ if (fieldnr>1) pattern=bmkinfo[1];
+ if (fieldnr>2) bookmark=bmkinfo[2];
+ DEBUGKPILOT<<"RegExp Bookmark, pattern="<<pattern<<", name="<<bookmark<<endl;
+ bmk=new docRegExpBookmark(pattern, bookmark);
+ if (bmk) {
+ bmk->from=1;
+ bmk->to=1;
+ fBmks.append(bmk);
+ }
+ }
+ } // fieldnr>0
+ } // !line.isEmpty()
+ } // while
+ return nr;
+}
+
+bool DOCConverter::convertTXTtoPDB() {
+ FUNCTIONSETUP;
+
+ if (!docdb) {
+ emit logError(i18n("Unable to open Database for writing"));
+ return false;
+ }
+
+ QString text = readText();
+
+ if (fBmkTypes & eBmkEndtags) {
+ findBmkEndtags(text, fBookmarks);
+ } // end: EndTag Bookmarks
+
+
+ // Search for all tags <* Bookmark text *> in the text. We have to delete them immediately, otherwise the later bookmarks will be off.
+ if (fBmkTypes & eBmkInline) {
+ findBmkInline(text, fBookmarks);
+ } // end: Inline Bookmarks
+
+
+ // Read in regular expressions and positions from an external file (doc-filename with extension .bmk)
+ if (fBmkTypes & eBmkFile)
+ {
+ findBmkFile(text, fBookmarks);
+ }
+
+ // Process the bookmarks: find the occurrences of the regexps, and sort them if requested:
+ bmkSortedList pdbBookmarks;
+ pdbBookmarks.setAutoDelete(TRUE);
+ docBookmark*bmk;
+ for (bmk = fBookmarks.first(); bmk; bmk = fBookmarks.next())
+ {
+ bmk->findMatches(text, pdbBookmarks);
+ }
+
+ switch (eSortBookmarks)
+ {
+ case eSortName:
+ docBookmark::compare_pos=false;
+// qHeapSort(pdbBookmarks);
+ pdbBookmarks.sort();
+ break;
+ case eSortPos:
+ docBookmark::compare_pos=true;
+ pdbBookmarks.sort();
+ break;
+ case eSortNone:
+ default:
+ break;
+ }
+
+#ifdef DEBUG
+ DEBUGKPILOT << "Bookmarks: "<<endl;
+ for (bmk = pdbBookmarks.first(); bmk; bmk = pdbBookmarks.next())
+ {
+ DEBUGKPILOT<<bmk->bmkName.left(20)<<" at position "<<bmk->position<<endl;
+ }
+#endif
+
+ if (!docdb->isOpen()) {
+ emit logError(i18n("Unable to open palm doc database %1").arg(docdb->dbPathName()) );
+ return false;
+ }
+
+ // Clean the whole database, otherwise the records would be just appended!
+ docdb->deleteRecord(0, true);
+
+ // Header record for the doc file format
+ PilotDOCHead docHead;
+ docHead.position=0;
+ docHead.recordSize=4096;
+ docHead.spare=0;
+ docHead.storyLen=text.length();
+ docHead.version=compress?DOC_COMPRESSED:DOC_UNCOMPRESSED;
+ docHead.numRecords=(int)( (text.length()-1)/docHead.recordSize)+1;
+ PilotRecord*rec=docHead.pack();
+ docdb->writeRecord(rec);
+ KPILOT_DELETE(rec);
+
+ DEBUGKPILOT << "Write header record: length="<<text.length()<<", compress="<<compress<<endl;
+
+ // First compress the text, then write out the bookmarks and - if existing - also the annotations
+ int len=text.length();
+ int start=0,reclen=0;
+ int recnum=0;
+ while (start<len)
+ {
+ reclen=min(len-start, PilotDOCEntry::TEXT_SIZE);
+ DEBUGKPILOT << "Record #"<<recnum<<", reclen="<<reclen<<", compress="<<compress<<endl;
+
+ PilotDOCEntry recText;
+// recText.setText(text.mid(start, reclen), reclen);
+ recText.setText(text.mid(start, reclen));
+// if (compress)
+ recText.setCompress(compress);
+ PilotRecord*textRec=recText.pack();
+ docdb->writeRecord(textRec);
+ ++recnum;
+ start+=reclen;
+ KPILOT_DELETE(textRec);
+ }
+
+ recnum=0;
+ // Finally, write out the bookmarks
+ for (bmk = pdbBookmarks.first(); bmk; bmk = pdbBookmarks.next())
+// for (bmkList::const_iterator it=pdbBookmarks.begin(); it!=pdbBookmarks.end(); ++it)
+ {
+ ++recnum;
+ DEBUGKPILOT << "Bookmark #"<<recnum<<", Name="<<bmk->bmkName.left(20)<<", Position="<<bmk->position<<endl;
+
+ PilotDOCBookmark bmkEntry;
+ bmkEntry.pos=bmk->position;
+ strncpy(&bmkEntry.bookmarkName[0], bmk->bmkName.latin1(), 16);
+ PilotRecord*bmkRecord=bmkEntry.pack();
+ docdb->writeRecord(bmkRecord);
+ KPILOT_DELETE(bmkRecord);
+ }
+
+ pdbBookmarks.clear();
+ fBookmarks.clear();
+
+ return true;
+}
+
+
+
+bool DOCConverter::convertPDBtoTXT()
+{
+ FUNCTIONSETUP;
+ if (txtfilename.isEmpty()) {
+ emit logError(i18n("No filename set for the conversion"));
+ return false;
+ }
+
+ if (!docdb) {
+ emit logError(i18n("Unable to open Database for reading"));
+ return false;
+ }
+
+ // The first record of the db is the document header containing information about the doc db
+ PilotRecord*headerRec = docdb->readRecordByIndex(0);
+ if (!headerRec)
+ {
+ emit logError(i18n("Unable to read database header for database %1.").arg(docdb->dbPathName()));
+ KPILOT_DELETE(docdb);
+ return false;
+ }
+ PilotDOCHead header(headerRec);
+ KPILOT_DELETE(headerRec);
+
+ DEBUGKPILOT<<"Database "<<docdb->dbPathName()<<" has "<<header.numRecords<<" text records, "<<endl
+ <<" total number of records: "<<docdb->recordCount()<<endl
+ <<" position="<<header.position<<endl
+ <<" recordSize="<<header.recordSize<<endl
+ <<" spare="<<header.spare<<endl
+ <<" storyLen="<<header.storyLen<<endl
+// <<" textRecordSize="<<header.textRecordSize<<endl
+ <<" version="<<header.version<<endl;
+
+ // next come the header.numRecords real document records (might be compressed, see the version flag in the header)
+ QFile docfile(txtfilename);
+ if (!docfile.open(IO_WriteOnly))
+ {
+ emit logError(i18n("Unable to open output file %1.").arg(txtfilename));
+ KPILOT_DELETE(docdb);
+ return false;
+ }
+ QString doctext;
+ for (int i=1; i<header.numRecords+1; ++i)
+ {
+ PilotRecord*rec=docdb->readRecordByIndex(i);
+ if (rec)
+ {
+ PilotDOCEntry recText(rec, header.version==DOC_COMPRESSED);
+ doctext.append(recText.getText());
+ DEBUGKPILOT<<"Record "<<i<<endl;
+ KPILOT_DELETE(rec);
+ } else {
+ emit logMessage(i18n("Could not read text record #%1 from Database %2").arg(i).arg(docdb->dbPathName()));
+ }
+ }
+
+ // After the document records possibly come a few bookmark records, so read them in and put them in a separate bookmark file.
+ // for the ztxt conduit there might be annotations after the bookmarks, so the upper bound needs to be adapted.
+ int upperBmkRec=docdb->recordCount();
+ bmkSortedList bmks;
+ bmks.setAutoDelete(TRUE);
+ for (int i=header.numRecords+1; i<upperBmkRec; ++i)
+ {
+ PilotRecord*rec=docdb->readRecordByIndex(i);
+ if (rec)
+ {
+ PilotDOCBookmark bookie(rec);
+ docBookmark*bmk=new docBookmark(QString::fromLatin1(bookie.bookmarkName), bookie.pos);
+ bmks.append(bmk);
+ KPILOT_DELETE(rec);
+ } else {
+ emit logMessage(i18n("Could not read bookmark record #%1 from Database %2").arg(i).arg(docdb->dbPathName()));
+ }
+ }
+ // TODO: Sort the list of bookmarks according to their position
+ docBookmark::compare_pos=true;
+ bmks.sort();
+
+ if ((fBmkTypes & eBmkFile) && (bmks.count()>0))
+ {
+ QString bmkfilename = docfile.name();
+ if (bmkfilename.endsWith(CSL1(".txt"))){
+ bmkfilename.remove(bmkfilename.length()-4, 4);
+ }
+ bmkfilename+=CSL1(PDBBMK_SUFFIX);
+ QFile bmkfile(bmkfilename);
+ if (!bmkfile.open(IO_WriteOnly))
+ {
+ emit logError(i18n("Unable to open file %1 for the bookmarks of %2.")
+ .arg(bmkfilename).arg(docdb ->dbPathName()));
+ }
+ else
+ {
+ DEBUGKPILOT<<"Writing "<<upperBmkRec-header.numRecords<<
+ "("<<upperBmkRec<<") bookmarks to file "<<bmkfilename<<endl;
+ QTextStream bmkstream(&bmkfile);
+ for (docBookmark*bmk=bmks.first(); bmk; bmk=bmks.next())
+ {
+ bmkstream<<bmk->position<<", "<<bmk->bmkName<<endl;
+ }
+ //bmkstream.close();
+ bmkfile.close();
+ }
+ }
+ if (fBmkTypes & eBmkInline)
+ {
+ for (docBookmark*bmk=bmks.last(); bmk; bmk=bmks.prev())
+ {
+ doctext.insert(bmk->position, QString(CSL1("<*") +
+ bmk->bmkName +
+ CSL1("*>")));
+ }
+ }
+
+ // Finally, write the actual text out to the file.
+ QTextStream docstream(&docfile);
+ docstream<<doctext;
+ //docstream.close();
+ docfile.close();
+ docdb->cleanup();
+ // reset all records to unchanged. I don't know if this is really such a wise idea?
+ docdb->resetSyncFlags();
+ return true;
+}
+
+
diff --git a/kpilot/conduits/docconduit/DOC-converter.h b/kpilot/conduits/docconduit/DOC-converter.h
new file mode 100644
index 000000000..f3747ea1d
--- /dev/null
+++ b/kpilot/conduits/docconduit/DOC-converter.h
@@ -0,0 +1,183 @@
+#ifndef _DOC_CONVERTER_H
+#define _DOC_CONVERTER_H
+/* DOC-converter.h KPilot
+**
+** Copyright (C) 2002-2003 by Reinhold Kainhofer
+**
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+
+
+#define DOC_UNCOMPRESSED 1
+#define DOC_COMPRESSED 2
+
+
+#define BMK_SUFFIX ".bmk"
+#define PDBBMK_SUFFIX ".bm"
+
+#include <qptrlist.h>
+#include <qobject.h>
+
+class PilotDatabase;
+
+
+/****************************************************************************************************
+ * various bookmark classes. Most important is the bmkList findMatches(QString, bmkList &) function,
+ * which needs to return a list of all bookmarks found for the given bookmark expression.
+ * A bookmark usually consists of a bookmark text and an offset into the text document.
+ ****************************************************************************************************/
+
+class docBookmark;
+#define bmkList QPtrList<docBookmark>
+#define bmkSortedList QSortedList<docBookmark>
+
+class docBookmark {
+public:
+ static bool compare_pos;
+ docBookmark():bmkName(), position(0) { };
+ docBookmark(QString name, long int pos):bmkName(name), position(pos) { };
+ docBookmark(const docBookmark &bmk):bmkName(bmk.bmkName),position(bmk.position){};
+ virtual ~ docBookmark() { };
+ virtual int findMatches(QString, bmkList &fBookmarks) {
+ FUNCTIONSETUP;
+ fBookmarks.append(new docBookmark(*this));
+ return 1;
+ };
+
+ QString bmkName;
+ long int position;
+};
+
+class docMatchBookmark:public docBookmark {
+ public:
+ docMatchBookmark():docBookmark() { from=0; to=100;};
+ docMatchBookmark(QString pattrn, int options=0):docBookmark(),
+ pattern(pattrn), opts(options) { from=0; to=100; };
+ docMatchBookmark(QString pattrn, QString bmkname,
+ int options=0):docBookmark(bmkname, 0), pattern(pattrn),
+ opts(options) { from=0; to=100; };
+ virtual ~ docMatchBookmark() { };
+
+ virtual int findMatches(QString, bmkList &fBookmarks);
+ QString pattern;
+ int opts;
+ int from, to;
+};
+
+class docRegExpBookmark:public docMatchBookmark {
+ public:
+ docRegExpBookmark():docMatchBookmark() { capSubexpression=-1;};
+ docRegExpBookmark(QString regexp, int cap=0,
+ int options=0):docMatchBookmark(regexp, options) {capSubexpression=cap; };
+ docRegExpBookmark(QString pattrn, QString bmkname,
+ int options=0):docMatchBookmark(pattrn, bmkname, options) { capSubexpression=-1; };
+ virtual ~ docRegExpBookmark() { };
+
+ virtual int findMatches(QString, bmkList &fBookmarks);
+ int capSubexpression;
+};
+
+
+/*************************************************************************************************************
+ * The converter class that does the real work for us.
+ *************************************************************************************************************/
+
+class DOCConverter:public QObject {
+Q_OBJECT
+private:
+ PilotDatabase * docdb;
+ QString txtfilename;
+ QString bmkfilename;
+ bool compress;
+
+ bmkList fBookmarks;
+public:
+ enum eSortBookmarksEnum
+ {
+ eSortNone,
+ eSortPos,
+ eSortName
+ } eSortBookmarks;
+
+public:
+ DOCConverter(QObject *parent=0L, const char *name=0L);
+ virtual ~ DOCConverter();
+
+ QString readText();
+ void setTXTpath(QString path, QString file);
+ void setTXTpath(QString filename);
+ void setPDB(PilotDatabase * dbi);
+ QString txtFilename() const {return txtfilename;}
+ QString bmkFilename() const {return bmkfilename;}
+ void setBmkFilename(QString bmkf) { bmkfilename=bmkf;}
+
+ bool getCompress() const { return compress; };
+ void setCompress(bool newcomp) {compress=newcomp;};
+
+ bool convertTXTtoPDB();
+ bool convertPDBtoTXT();
+
+ int setBookmarks(bmkList bookmarks) {
+ fBookmarks = bookmarks;
+ return fBookmarks.count();
+ };
+ int clearBookmarks() {
+ fBookmarks.clear();
+ return fBookmarks.count();
+ };
+ int addBookmark(docBookmark*bookmark) {
+ fBookmarks.append(bookmark);
+ return fBookmarks.count();
+ };
+
+ int findBmkEndtags(QString &, bmkList&);
+ int findBmkInline(QString &, bmkList&);
+ int findBmkFile(QString &, bmkList&);
+
+
+ void setSort(enum eSortBookmarksEnum sort) {eSortBookmarks=sort;}
+ enum eSortBookmarksEnum getSort() {return eSortBookmarks;}
+
+ enum eBmkTypesEnum {
+ eBmkNone = 0,
+ eBmkFile = 1,
+ eBmkInline = 2,
+ eBmkEndtags = 4,
+ eBmkDefaultBmkFile = 8
+ } fBmkTypes;
+ void setBookmarkTypes(int types) {
+ fBmkTypes = (eBmkTypesEnum) types;
+ };
+
+protected:
+ int findBookmarks();
+
+private:
+ void readConfig();
+signals:
+ void logMessage(const QString &);
+ void logError(const QString &);
+};
+
+#endif
diff --git a/kpilot/conduits/docconduit/Icons/CMakeLists.txt b/kpilot/conduits/docconduit/Icons/CMakeLists.txt
new file mode 100644
index 000000000..3d1034d44
--- /dev/null
+++ b/kpilot/conduits/docconduit/Icons/CMakeLists.txt
@@ -0,0 +1,3 @@
+
+kde3_install_icons_custom( hicolor )
+
diff --git a/kpilot/conduits/docconduit/Icons/Makefile.am b/kpilot/conduits/docconduit/Icons/Makefile.am
new file mode 100644
index 000000000..f371f4aed
--- /dev/null
+++ b/kpilot/conduits/docconduit/Icons/Makefile.am
@@ -0,0 +1,7 @@
+METASOURCES = AUTO
+
+kpalmdocicondir = $(kde_datadir)/kpilot/icons
+kpalmdocicon_ICON = kpalmdoc
+
+KDE_ICON = kpalmdoc
+
diff --git a/kpilot/conduits/docconduit/Icons/cr16-app-kpalmdoc.png b/kpilot/conduits/docconduit/Icons/cr16-app-kpalmdoc.png
new file mode 100644
index 000000000..0f5fb75d5
--- /dev/null
+++ b/kpilot/conduits/docconduit/Icons/cr16-app-kpalmdoc.png
Binary files differ
diff --git a/kpilot/conduits/docconduit/Icons/cr22-app-kpalmdoc.png b/kpilot/conduits/docconduit/Icons/cr22-app-kpalmdoc.png
new file mode 100644
index 000000000..d93aa4bae
--- /dev/null
+++ b/kpilot/conduits/docconduit/Icons/cr22-app-kpalmdoc.png
Binary files differ
diff --git a/kpilot/conduits/docconduit/Icons/cr32-app-kpalmdoc.png b/kpilot/conduits/docconduit/Icons/cr32-app-kpalmdoc.png
new file mode 100644
index 000000000..09a7020b5
--- /dev/null
+++ b/kpilot/conduits/docconduit/Icons/cr32-app-kpalmdoc.png
Binary files differ
diff --git a/kpilot/conduits/docconduit/Icons/cr48-app-kpalmdoc.png b/kpilot/conduits/docconduit/Icons/cr48-app-kpalmdoc.png
new file mode 100644
index 000000000..41cb3b9b1
--- /dev/null
+++ b/kpilot/conduits/docconduit/Icons/cr48-app-kpalmdoc.png
Binary files differ
diff --git a/kpilot/conduits/docconduit/Makefile.am b/kpilot/conduits/docconduit/Makefile.am
new file mode 100644
index 000000000..77df2b61b
--- /dev/null
+++ b/kpilot/conduits/docconduit/Makefile.am
@@ -0,0 +1,38 @@
+### Makefile for KPilot's doc conduit
+###
+### The doc conduit is Copyright (C) 2002 by Reinhold Kainhofer
+### the files makedoc9.{h,cpp} are also Copyright (C) 2000 by Pat Beirne
+
+SUBDIRS = Icons
+
+INCLUDES= $(PISOCK_INCLUDE) -I$(top_srcdir)/kpilot/lib $(all_includes)
+METASOURCES = AUTO
+
+
+servicedir = $(kde_servicesdir)
+service_DATA = doc_conduit.desktop
+
+noinst_LTLIBRARIES = libpalmdoc_shared.la
+kde_module_LTLIBRARIES = conduit_doc.la
+bin_PROGRAMS = kpalmdoc
+
+libpalmdoc_shared_la_SOURCES = makedoc9.cc pilotDOCHead.cc pilotDOCEntry.cc pilotDOCBookmark.cc DOC-converter.cc
+
+conduit_doc_la_SOURCES = docconduitSettings.kcfgc doc-factory.cc doc-setup.cc doc-conduit.cc doc-setupdialog.ui doc-conflictdialog.cc
+conduit_doc_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries)
+conduit_doc_la_LIBADD = ../../lib/libkpilot.la libpalmdoc_shared.la \
+ $(LIB_KDEUI) $(LIB_KFILE)
+
+##libpalmdoc_shared.la
+
+kpalmdoc_SOURCES = kpalmdocSettings.kcfgc kpalmdoc_dlgbase.ui kpalmdoc_dlg.cc kpalmdoc.cpp
+kpalmdoc_LDFLAGS = $(PISOCK_LDFLAGS) $(all_libraries) $(KDE_RPATH)
+kpalmdoc_LDADD = $(LIB_KFILE) $(PISOCK_LIB) ../../lib/libkpilot.la libpalmdoc_shared.la
+
+xdg_apps_DATA = kpalmdoc.desktop
+servicetypedir = $(kde_servicetypesdir)
+kde_kcfg_DATA = docconduit.kcfg kpalmdoc.kcfg
+
+update_DATA = kpalmdoc.upd
+updatedir = $(kde_datadir)/kconf_update
+
diff --git a/kpilot/conduits/docconduit/bmkSpecification.txt b/kpilot/conduits/docconduit/bmkSpecification.txt
new file mode 100644
index 000000000..f8a68d961
--- /dev/null
+++ b/kpilot/conduits/docconduit/bmkSpecification.txt
@@ -0,0 +1,199 @@
+KPilot PalmDoc Conduit bookmark Specification
+=============================================
+
+(c) 2003 Reinhold Kainhofer, reinhold@kainhofer.com
+
+This document is licensed under the FDL (Free Documentation License)
+as published by the FSF. Any version of the FDL can be applied
+at your convenience.
+
+
+
+
+The PalmDoc conduit has three ways to indicate bookmarks for a text:
+ -) Inline tags of the form <* bookmarkname *>
+ -) Endtags of the form <bookmarkname> at the end of the document
+ -) Regular expressions in a separate textname.bmk file
+ (textname.bmk ist the filename of the text with the .txt replaced by .bmk)
+
+
+In the design of the .bmk file, I tried to stay close to the
+syntac of MakeDocJ bookmark files, but it turned out that I
+needed to extend the syntax a little. Also, MakeDocJ uses Java
+RegExps, while the PalmDoc conduit uses the QRegExp, which have
+some slight differences (especially concerning the ^ and $
+patterns as well as backreferences). So if you used MakeDocJ,
+the .bmk file syntax will be quite familiar, but you will still
+have to adapt your bookmark files for Qt regular expressions
+instead of Java regular expressions
+
+
+
+1) INLINE TAGS
+
+Whenever a tag of the form <* someText *> appears in the text,
+this sequence is removed from the text, and a bookmark is set
+there with the bookmark name "someText" (the part between the
+<* and the *>).
+
+
+2) ENDTAGS
+
+If the text ends with tags of the form <someText>, the string
+in braces is used as bookmark name, and wherever it appears in
+the text, a bookmark is set.
+After the > any number of whitespace is allowed, but no other
+characters like letters, numbers, or punctuation. Also, inside
+the braces no line break must occur. The conduit searches the
+text from the end and if it finds a line break inside a <...>
+sequence, the tag and everything before it is assumed to belong
+to the text and doesn't form a bookmark tag.
+Between endtags any number of whitespace (spaces, tabs, line
+feeds etc.) is allowed.
+
+As an example, assume you have a text ending in:
+... the bad guy was punished, and they lived happily
+ever after!
+<Tag with
+line feed>
+ <bad guy> <princess>
+<married>
+
+The conduit starts at the end, ignores all whitespace between
+the tags, so it finds the tags "married", "princess", and "bad guy".
+The "Tag with line feed" has a line feed, so it is assumed to belong
+to the text.
+Assume now you have a text ending in:
+... the bad guy was punished, and they lived happily
+ever after!
+<bad guy> The End <princess>
+<married>
+
+Here, only "married" and "princess" are found as bookmarks. Because
+of the letters before the "princess" tags, the search for the
+bookmarks ends at the letter "d" of "The End" (the conduit starts
+from the end and moves backward until it finds some text which
+cannot be seen as a endtag.
+
+
+
+
+3) REGULAR EXPRESSIONS IN A SEPARATE FILE
+
+This is by far the most complex way to specify bookmarks, but
+it is also the mose powerful.
+If you have a text with filename "My fairy tale.txt", the
+bookmarks will be specified in a file called "My fairy tale.bmk"
+(just the text filename with the .txt replaced by .bmk). This
+file contains the bookmark definitions, one in each line. Lines
+starting with a # are seen as comments, and empty lines are also
+ignored.
+
+
+In the .bmk file, each bookmark line has one of the following syntaces
+(I will explain all fields later on). Fields in [..] are optional:
+
+bmkName
+bmkPosition, bmkName
++, bmkPatternRegExp[, bmkNameAsString[, firstIncludedBmk[, lastIncludedBmk]]]
++, bmkPatternRegExp[, bmkNameIndexOfSubexpression[, firstIncludedBmk[, lastIncludedBmk]]]
+-, bmkPatternRegExp[, bmkNameAsString]
+-, bmkPatternRegExp[, bmkNameIndexOfSubexpression]
+
+ If the first field is a string, it is used as the bookmark name
+and pattern to search for.
+ If the first field is a number, it means the position of the
+bookmark, and the second field is the name of the bookmark.
+ If the first field is either + or -, the second field gives
+a regular expression that is used to find the position of the
+bookmark. If the first field is a -, the search is done only
+once and only the first match will be added as bookmark. If
+the first field is a +, the search is done until the regular
+expression can no longer be found (the fourth and fifth fields
+can be used to include only a certain range of hits). If there
+is a third field, and it is a string, it gives the name of the
+bookmark as a regular expression (i.e. \1 are replaced by the
+first subexpression of the search, where subexpressions are
+specified by round brackets in the regexp of the second field).
+If there is a third field, and it is a number, it gives the index
+of the subexpression of bmkPatternRegExp that is used as the
+bookmark name.
+If there is no third field, the whole matched text will be used
+as bookmark name.
+The optional fourth and fifth fields can be used to set bookmarks
+only after the first few ocurrences of the regexp in the text, and
+to stop the search after the expression has been found a certain
+number of times.
+
+
+
+If the PDB->PC sync is set up to store the bookmarks in a bookmark file,
+it will create a file "My fairy tale.bm" (no "k") with entries of the form
+position,bmkName
+The .bmk file will be used if it exists, but if no .bmk file exists, the .bm file
+will be used. This way you can override the bookmark settings, while
+at the same time the PDB->TXT sync does not destroy your possibly
+existing .bmk file.
+
+
+
+Examples:
+
+1) Imagine you have a line like:
+frog princess
+In this case, the text is searched for "frog princess", and a
+bookmark is set whenever "frog princess" occurs in the text.
+The name of each of these bookmarks will be "frog princess".
+
+2) A bookmark line:
+55, Bookmark at offset 55
+Here, a bookmark will be set at offset 55 (55th character of
+the text), and it will have the name "Bookmark at offs" (truncated
+to 16 characters)
+
+3) A bookmark line
+-,Chapter \d+
+causes a bookmark to be set at the first ocurrence of "Chapter XXX",
+where XXX denotes one or more digits. The bookmark name will be
+"Chapter XXX" (XXX replaced by the actual digits).
+
+4) A bookmark line
++,Chapter \d+
+causes bookmarks to be set wherever "Chapter XXX" (XXX being one
+or more digits) appears in the text. The bookmark name will again
+be "Chapter XXX", but the search does not stop after the first hit.
+
+5) A bookmark line
++,\n\s*(Chapter \d+)\D+, 1
+causes a bookmark to be set whenever a new line starts with
+"Chapter XXX" (whitespace is allowed before the "Chapter"), and
+uses the first subexpression in (..) as the bookmark name. If you
+have a passage
+ Chapter 15: here it starts
+The regular expression will match, so a bookmark will be set there
+and the subexpression "Chapter 15" (which matches the (Chapter \d+) )
+will be used as bookmark text.
+
+6) A bookmark line
++,\n\s*Part (\d+),\1\. part
+sets a bookmark whenever a line starts with "Part XXX". The XXX
+will be stored as the first matched subexpression. The third field
+"\1\. part" is the regular expression for the bookmark name, where
+\1 is replaced by the first matched subexpression of the search (XXX
+in this case). So if a line starts with " Part 17: ", the bookmark
+name will be "17. part".
+
+7) A bookmark line
++,Table (\d+): ,\1\. Tabelle,5,25
+will match whenever "Table XXX: " appears in the text, and the bookmark
+name will be "XXX. Tabelle". However, the fourth field means that the
+first four hits are ignored (the 5th hit is the first hit to be included
+as a bookmark), and the fifth field means that all further hits after the
+25th will be ignored, too.
+
+8) In law texts, I use a regular expression
++,\n *(§\.? *\d+[a-z]?\.?) +, 1
+to search for all paragraphs starting like "§. 15. " or " §23 ", and set
+a bookmark there using only the part from the § to the last digit or the
+full stop after the last digit (the pattern between the (), in our two
+cases the bookmark names will be "§. 15." and "§23" ).
diff --git a/kpilot/conduits/docconduit/doc-conduit.cc b/kpilot/conduits/docconduit/doc-conduit.cc
new file mode 100644
index 000000000..eee36080c
--- /dev/null
+++ b/kpilot/conduits/docconduit/doc-conduit.cc
@@ -0,0 +1,1018 @@
+/* KPilot
+**
+** Copyright (C) 2002 by Reinhold Kainhofer
+**
+** The doc conduit synchronizes text files on the PC with DOC databases on the Palm
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org.
+*/
+
+
+// naming of the bookmark file:
+// PDB->TXT: convert bookmarks to a .bm file
+// TXT->PDB: If a .bmk file exists, use it, otherwise use the .bm file (from the PDB->TXT conversion)
+// This way, the bookmark file is not overwritten, a manual bookmark file overrides, but the bookmarks from the handheld are still available
+
+
+#include "options.h"
+#include "doc-conduit.moc"
+
+#include <qtimer.h>
+#include <qdir.h>
+
+#include <kconfig.h>
+#include <kmdcodec.h>
+
+#include <pilotLocalDatabase.h>
+#include <pilotSerialDatabase.h>
+
+#include "doc-factory.h"
+#include "doc-conflictdialog.h"
+#include "DOC-converter.h"
+#include "pilotDOCHead.h"
+#include "docconduitSettings.h"
+
+
+// Something to allow us to check what revision
+// the modules are that make up a binary distribution.
+extern "C"
+{
+unsigned long version_conduit_doc = Pilot::PLUGIN_API;
+}
+
+QString dirToString(eSyncDirectionEnum dir) {
+ switch(dir) {
+// case eSyncAll: return "eSyncAll";
+ case eSyncPDAToPC: return CSL1("eSyncPDAToPC");
+ case eSyncPCToPDA: return CSL1("eSyncPCToPDA");
+ case eSyncNone: return CSL1("eSyncNone");
+ case eSyncConflict: return CSL1("eSyncConflict");
+ case eSyncDelete: return CSL1("eSyncDelete");
+ default: return CSL1("ERROR");
+ }
+}
+
+
+/*********************************************************************
+ C O N S T R U C T O R
+ *********************************************************************/
+
+
+DOCConduit::DOCConduit(KPilotLink * o,
+ const char *n, const QStringList & a):ConduitAction(o, n, a)
+{
+ FUNCTIONSETUP;
+ fConduitName=i18n("DOC");
+}
+
+
+
+DOCConduit::~DOCConduit()
+{
+ FUNCTIONSETUP;
+}
+
+
+bool DOCConduit::isCorrectDBTypeCreator(DBInfo dbinfo) {
+ return dbinfo.type == dbtype() && dbinfo.creator == dbcreator();
+}
+const unsigned long DOCConduit::dbtype() {
+ return get_long(DOCConduitFactory::dbDOCtype);
+}
+const unsigned long DOCConduit::dbcreator() {
+ return get_long(DOCConduitFactory::dbDOCcreator);
+}
+
+
+
+/*********************************************************************
+ L O A D I N G T H E D A T A
+ *********************************************************************/
+
+
+
+void DOCConduit::readConfig()
+{
+ FUNCTIONSETUP;
+ DOCConduitSettings::self()->readConfig();
+
+ eConflictResolution = (enum eSyncDirectionEnum) (DOCConduitSettings::conflictResolution() );
+ fTXTBookmarks = DOCConverter::eBmkNone;
+ if ( DOCConduitSettings::convertBookmarks() )
+ {
+ if ( DOCConduitSettings::bmkFileBookmarks() )
+ fTXTBookmarks |= DOCConverter::eBmkFile;
+ if ( DOCConduitSettings::inlineBookmarks() )
+ fTXTBookmarks |= DOCConverter::eBmkInline;
+ if ( DOCConduitSettings::endtagBookmarks() )
+ fTXTBookmarks |= DOCConverter::eBmkEndtags;
+ }
+
+ eSyncDirection = (enum eSyncDirectionEnum)(DOCConduitSettings::syncDirection() );
+
+#ifdef DEBUG
+ DEBUGKPILOT << fname
+ << ": Settings "
+ << " tXTDirectory=" << DOCConduitSettings::tXTDirectory()
+ << " pDBDirectory=" << DOCConduitSettings::pDBDirectory()
+ << " keepPDBLocally=" << DOCConduitSettings::keepPDBsLocally()
+ << " eConflictResolution=" << eConflictResolution
+ << " tXTBookmarks=" << fTXTBookmarks
+ << " pDBBookmarks=" << DOCConduitSettings::bookmarksToPC()
+ << " compress=" << DOCConduitSettings::compress()
+ << " eSyncDirection=" << eSyncDirection << endl;
+#endif
+}
+
+
+
+bool DOCConduit::pcTextChanged(QString txtfn)
+{
+ FUNCTIONSETUP;
+ // How do I find out if a text file has changed shince we last synced it??
+ // Use KMD5 for now. If I realize it is too slow, then I have to go back to comparing modification times
+ // if there is no config setting yet, assume the file has been changed. the md5 sum will be written to the config file after the sync.
+ QString oldDigest=DOCConduitSettings::self()->config()->readEntry(txtfn);
+ if (oldDigest.length()<=0)
+ {
+ return true;
+ }
+#ifdef DEBUG
+ DEBUGKPILOT<<"Old digest is "<<oldDigest<<endl;
+#endif
+
+ KMD5 docmd5;
+ QFile txtfile(txtfn);
+ if (txtfile.open(IO_ReadOnly)){
+ docmd5.update(txtfile);
+ QString thisDigest(docmd5.hexDigest() /* .data() */);
+#ifdef DEBUG
+ DEBUGKPILOT<<"New digest is "<<thisDigest<<endl;
+#endif
+ return (thisDigest.length()<=0) || (thisDigest!=oldDigest);
+ } else {
+ // File does not exist. This should actually never happen. Anyways, just return true to indicate it has changed.
+ // doSync should detect this and delete the doc from the handheld.
+ return true;
+ }
+ return false;
+}
+
+
+
+bool DOCConduit::hhTextChanged(PilotDatabase*docdb)
+{
+ FUNCTIONSETUP;
+ if (!docdb) return false;
+
+ PilotRecord *firstRec = docdb->readRecordByIndex(0);
+ PilotDOCHead docHeader(firstRec);
+ KPILOT_DELETE(firstRec);
+
+ int storyRecs = docHeader.numRecords;
+
+ // determine the index of the next modified record (does it lie
+ // beyond the actual text records?)
+ int modRecInd=-1;
+ PilotRecord*modRec=docdb->readNextModifiedRec(&modRecInd);
+#ifdef DEBUG
+ DEBUGKPILOT<<"Index of first changed record: "<<modRecInd<<endl;
+#endif
+
+ KPILOT_DELETE(modRec);
+ // if the header record was changed, find out which is the first changed
+ // real document record:
+ if (modRecInd==0) {
+ modRec=docdb->readNextModifiedRec(&modRecInd);
+#ifdef DEBUG
+ DEBUGKPILOT<<"Reread Index of first changed records: "<<modRecInd<<endl;
+#endif
+ KPILOT_DELETE(modRec);
+ }
+
+ // The record index starts with 0, so only a negative number means
+ // no modified record was found
+ if (modRecInd >= 0) {
+#ifdef DEBUG
+ DEBUGKPILOT<<"Handheld side has changed, condition="<<
+ ((!DOCConduitSettings::ignoreBmkChanges()) || (modRecInd <= storyRecs))<<endl;
+#endif
+ if ((!DOCConduitSettings::ignoreBmkChanges()) || (modRecInd <= storyRecs))
+ return true;
+ } else {
+#ifdef DEBUG
+ DEBUGKPILOT<<"Handheld side has NOT changed!"<<endl;
+#endif
+ return false;
+ }
+ return false;
+}
+
+
+
+/*********************************************************************
+ * Helper functions
+ ********************************************************************/
+
+QString DOCConduit::constructPDBFileName(QString name) {
+ FUNCTIONSETUP;
+ QString fn;
+ QDir dr(DOCConduitSettings::pDBDirectory());
+ QFileInfo pth(dr, name);
+ if (!name.isEmpty()) fn=pth.absFilePath()+CSL1(".pdb");
+ return fn;
+}
+QString DOCConduit::constructTXTFileName(QString name) {
+ FUNCTIONSETUP;
+ QString fn;
+ QDir dr( DOCConduitSettings::tXTDirectory() );
+ QFileInfo pth(dr, name);
+ if (!name.isEmpty()) fn=pth.absFilePath()+CSL1(".txt");
+ return fn;
+}
+
+
+
+
+
+/*********************************************************************
+ S Y N C S T R U C T U R E
+ *********************************************************************/
+
+
+
+
+
+/* virtual */ bool DOCConduit::exec()
+{
+ FUNCTIONSETUP;
+
+ readConfig();
+ dbnr=0;
+
+ emit logMessage(i18n("Searching for texts and databases to synchronize"));
+
+ QTimer::singleShot(0, this, SLOT(syncNextDB()));
+ return true;
+}
+
+
+
+bool DOCConduit::doSync(docSyncInfo &sinfo)
+{
+ FUNCTIONSETUP;
+ bool res=false;
+
+ if (sinfo.direction==eSyncDelete) {
+ if (!sinfo.txtfilename.isEmpty()) {
+ if (!QFile::remove(sinfo.txtfilename)) {
+ WARNINGKPILOT << "Unable to delete the text file " << sinfo.txtfilename << " on the PC" << endl;
+ }
+ QString bmkfilename = sinfo.txtfilename;
+ if (bmkfilename.endsWith(CSL1(".txt"))){
+ bmkfilename.remove(bmkfilename.length()-4, 4);
+ }
+ bmkfilename+=CSL1(PDBBMK_SUFFIX);
+ if (!QFile::remove(bmkfilename)) {
+#ifdef DEBUG
+ DEBUGKPILOT<<"Could not remove bookmarks file "<<bmkfilename<<" for database "<<sinfo.handheldDB<<endl;
+#endif
+ }
+ }
+ if (!sinfo.pdbfilename.isEmpty() && DOCConduitSettings::keepPDBsLocally() ) {
+ PilotLocalDatabase*database=new PilotLocalDatabase(DOCConduitSettings::pDBDirectory(),
+ QString::fromLatin1(sinfo.dbinfo.name), false);
+ if (database) {
+ if ( database->deleteDatabase() !=0 ) {
+ WARNINGKPILOT << "Unable to delete database " << sinfo.dbinfo.name << " on the PC" << endl;
+ }
+ KPILOT_DELETE(database);
+ }
+ }
+ if (!DOCConduitSettings::localSync()) {
+ PilotDatabase *database=deviceLink()->database( sinfo.dbinfo.name );
+ if ( database->deleteDatabase() !=0 ) {
+ WARNINGKPILOT << "Unable to delete database " << sinfo.dbinfo.name << " from the handheld" << endl;
+ }
+ KPILOT_DELETE(database);
+ }
+ return true;
+ }
+ // preSyncAction should initialize the custom databases/files for the
+ // specific action chosen for this db and return a pointer to a docDBInfo
+ // instance which points either to a local database or a database on the handheld.
+ PilotDatabase *database = preSyncAction(sinfo);
+
+ if (database && ( !database->isOpen() ) ) {
+#ifdef DEBUG
+ DEBUGKPILOT<<"Database "<<sinfo.dbinfo.name<<" does not yet exist. Creating it:"<<endl;
+#endif
+ if (!database->createDatabase(dbcreator(), dbtype()) ) {
+#ifdef DEBUG
+ DEBUGKPILOT<<"Failed"<<endl;
+ emit logMessage(i18n("Database created."));
+#endif
+ }
+ }
+
+ if (database && database->isOpen()) {
+ DOCConverter docconverter;
+ connect(&docconverter, SIGNAL(logError(const QString &)), SIGNAL(logError(const QString &)));
+ connect(&docconverter, SIGNAL(logMessage(const QString &)), SIGNAL(logMessage(const QString &)));
+
+ docconverter.setTXTpath( DOCConduitSettings::tXTDirectory(), sinfo.txtfilename );
+ docconverter.setPDB(database);
+ docconverter.setCompress(DOCConduitSettings::compress());
+
+ switch (sinfo.direction) {
+ case eSyncPDAToPC:
+ docconverter.setBookmarkTypes(DOCConduitSettings::bookmarksToPC());
+ res = docconverter.convertPDBtoTXT();
+ break;
+ case eSyncPCToPDA:
+ docconverter.setBookmarkTypes(fTXTBookmarks);
+ res = docconverter.convertTXTtoPDB();
+ break;
+ default:
+ break;
+ }
+
+ // Now calculate the md5 checksum of the PC text and write it to the config file
+ if (res)
+ {
+ KMD5 docmd5;
+ QFile txtfile(docconverter.txtFilename());
+ if (txtfile.open(IO_ReadOnly)) {
+ docmd5.update(txtfile);
+ QString thisDigest(docmd5.hexDigest() /* .data() */);
+ DOCConduitSettings::self()->config()->writeEntry(docconverter.txtFilename(), thisDigest);
+ DOCConduitSettings::self()->config()->sync();
+#ifdef DEBUG
+ DEBUGKPILOT<<"MD5 Checksum of the text "<<sinfo.txtfilename<<" is "<<thisDigest<<endl;
+#endif
+ } else {
+#ifdef DEBUG
+ DEBUGKPILOT<<"couldn't open file "<<docconverter.txtFilename()<<" for reading!!!"<<endl;
+#endif
+ }
+ }
+
+ if (!postSyncAction(database, sinfo, res))
+ emit logError(i18n("Unable to install the locally created PalmDOC %1 to the handheld.")
+ .arg(QString::fromLatin1(sinfo.dbinfo.name)));
+ if (!res)
+ emit logError(i18n("Conversion of PalmDOC \"%1\" failed.")
+ .arg(QString::fromLatin1(sinfo.dbinfo.name)));
+// disconnect(&docconverter, SIGNAL(logError(const QString &)), SIGNAL(logError(const QString &)));
+// disconnect(&docconverter, SIGNAL(logMessage(const QString &)), SIGNAL(logMessage(const QString &)));
+// KPILOT_DELETE(database);
+ }
+ else
+ {
+ emit logError(i18n("Unable to open or create the database %1.")
+ .arg(QString::fromLatin1(sinfo.dbinfo.name)));
+ }
+ return res;
+}
+
+
+/** syncNextDB walks through all PalmDoc databases on the handheld and decides if they are supposed to be synced to the PC.
+ * syncNextDB and syncNextTXT fist build the list of all PalmDoc texts, and then the method syncDatabases does the actual sync. */
+void DOCConduit::syncNextDB() {
+ FUNCTIONSETUP;
+ DBInfo dbinfo;
+
+ if (eSyncDirection==eSyncPCToPDA || fHandle->findDatabase(NULL, &dbinfo, dbnr, dbtype(), dbcreator() /*, cardno */ ) < 0)
+ {
+ // no more databases available, so check for PC->Palm sync
+ QTimer::singleShot(0, this, SLOT(syncNextTXT()));
+ return;
+ }
+ dbnr=dbinfo.index+1;
+#ifdef DEBUG
+ DEBUGKPILOT<<"Next Palm database to sync: "<<dbinfo.name<<", Index="<<dbinfo.index<<endl;
+#endif
+
+ // if creator and/or type don't match, go to next db
+ if (!isCorrectDBTypeCreator(dbinfo) ||
+ fDBNames.contains(QString::fromLatin1(dbinfo.name)))
+ {
+ QTimer::singleShot(0, this, SLOT(syncNextDB()));
+ return;
+ }
+
+ QString txtfilename=constructTXTFileName(QString::fromLatin1(dbinfo.name));
+ QString pdbfilename=constructPDBFileName(QString::fromLatin1(dbinfo.name));
+
+ docSyncInfo syncInfo(QString::fromLatin1(dbinfo.name),
+ txtfilename, pdbfilename, eSyncNone);
+ syncInfo.dbinfo=dbinfo;
+ needsSync(syncInfo);
+ fSyncInfoList.append(syncInfo);
+ fDBNames.append(QString::fromLatin1(dbinfo.name));
+
+ QTimer::singleShot(0, this, SLOT(syncNextDB()));
+ return;
+}
+
+
+
+void DOCConduit::syncNextTXT()
+{
+ FUNCTIONSETUP;
+
+ if (eSyncDirection==eSyncPDAToPC )
+ {
+ // We don't sync from PC to PDB, so start the conflict resolution and then the actual sync process
+ docnames.clear();
+ QTimer::singleShot(0, this, SLOT(checkPDBFiles()));
+ return;
+ }
+
+ // if docnames isn't initialized, get a list of all *.txt files in DOCConduitSettings::tXTDirectory()
+ if (docnames.isEmpty()/* || dociterator==docnames.end() */) {
+ docnames=QDir( DOCConduitSettings::tXTDirectory(), CSL1("*.txt")).entryList() ;
+ dociterator=docnames.begin();
+ }
+ if (dociterator==docnames.end()) {
+ // no more databases available, so start the conflict resolution and then the actual sync proces
+ docnames.clear();
+ QTimer::singleShot(0, this, SLOT(checkPDBFiles()));
+ return;
+ }
+
+ QString fn=(*dociterator);
+
+ QDir dr( DOCConduitSettings::tXTDirectory() );
+ QFileInfo fl(dr, fn );
+ QString txtfilename=fl.absFilePath();
+ QString pdbfilename;
+ ++dociterator;
+
+ DBInfo dbinfo;
+ // Include all "extensions" except the last. This allows full stops inside the database name (e.g. abbreviations)
+ // first fill everything with 0, so we won't have a buffer overflow.
+ memset(&dbinfo.name[0], 0, 33);
+ strncpy(&dbinfo.name[0], fl.baseName(TRUE).latin1(), 30);
+
+ bool alreadySynced=fDBNames.contains(fl.baseName(TRUE));
+ if (!alreadySynced) {
+ docSyncInfo syncInfo(QString::fromLatin1(dbinfo.name),
+ txtfilename, pdbfilename, eSyncNone);
+ syncInfo.dbinfo=dbinfo;
+ needsSync(syncInfo);
+ fSyncInfoList.append(syncInfo);
+ fDBNames.append(QString::fromLatin1(dbinfo.name));
+ } else {
+#ifdef DEBUG
+ DEBUGKPILOT<<txtfilename<<" has already been synced, skipping it."<<endl;
+#endif
+ }
+
+ QTimer::singleShot(0, this, SLOT(syncNextTXT()));
+ return;
+}
+
+
+
+/** This slot will only be used if DOCConduitSettings::keepPDBsLocally() to check if new doc databases have been copied to the pdb directory.
+ * If so, install it to the handheld and sync it to the PC */
+void DOCConduit::checkPDBFiles() {
+ FUNCTIONSETUP;
+
+ if ( DOCConduitSettings::localSync() || !DOCConduitSettings::keepPDBsLocally() || eSyncDirection==eSyncPCToPDA )
+ {
+ // no more databases available, so check for PC->Palm sync
+ QTimer::singleShot(0, this, SLOT(checkDeletedDocs()));
+ return;
+ }
+
+ // Walk through all files in the pdb directory and check if it has already been synced.
+ // if docnames isn't initialized, get a list of all *.pdb files in DOCConduitSettings::pDBDirectory()
+ if (docnames.isEmpty()/* || dociterator==docnames.end() */) {
+ docnames=QDir(DOCConduitSettings::pDBDirectory(), CSL1("*.pdb")).entryList() ;
+ dociterator=docnames.begin();
+ }
+ if (dociterator==docnames.end()) {
+ // no more databases available, so start the conflict resolution and then the actual sync proces
+ docnames.clear();
+ QTimer::singleShot(0, this, SLOT(checkDeletedDocs()));
+ return;
+ }
+
+ QString fn=(*dociterator);
+
+ QDir dr(DOCConduitSettings::pDBDirectory());
+ QFileInfo fl(dr, fn );
+ QString pdbfilename=fl.absFilePath();
+ ++dociterator;
+
+ // Get the doc title and check if it has already been synced (in the synced docs list of in fDBNames to be synced)
+ // If the doc title doesn't appear in either list, install it to the Handheld, and add it to the list of dbs to be synced.
+ QString dbname=fl.baseName(TRUE).left(30);
+ if (!fDBNames.contains(dbname) && !fDBListSynced.contains(dbname)) {
+ if (fHandle->installFiles(pdbfilename, false)) {
+ DBInfo dbinfo;
+ // Include all "extensions" except the last. This allows full stops inside the database name (e.g. abbreviations)
+ // first fill everything with 0, so we won't have a buffer overflow.
+ memset(&dbinfo.name[0], 0, 33);
+ strncpy(&dbinfo.name[0], dbname.latin1(), 30);
+
+ docSyncInfo syncInfo(dbname, constructTXTFileName(dbname), pdbfilename, eSyncNone);
+ syncInfo.dbinfo=dbinfo;
+ needsSync(syncInfo);
+ fSyncInfoList.append(syncInfo);
+ fDBNames.append(dbname);
+ } else {
+#ifdef DEBUG
+ DEBUGKPILOT<<"Could not install database "<<dbname<<" ("<<pdbfilename<<") to the handheld"<<endl;
+#endif
+ }
+ }
+
+ QTimer::singleShot(0, this, SLOT(checkPDBFiles()));
+}
+
+
+
+void DOCConduit::checkDeletedDocs()
+{
+ FUNCTIONSETUP;
+
+ for (QStringList::Iterator it=fDBListSynced.begin(); it!=fDBListSynced.end(); ++it ) {
+ if (!fDBNames.contains(*it)) {
+ // We need to delete this doc:
+ QString dbname(*it);
+ QString txtfilename=constructTXTFileName(dbname);
+ QString pdbfilename=constructPDBFileName(dbname);
+ docSyncInfo syncInfo(dbname, txtfilename, pdbfilename, eSyncDelete);
+
+ DBInfo dbinfo;
+ memset(&dbinfo.name[0], 0, 33);
+ strncpy(&dbinfo.name[0], dbname.latin1(), 30);
+ syncInfo.dbinfo=dbinfo;
+
+ fSyncInfoList.append(syncInfo);
+ }
+ }
+ QTimer::singleShot(0, this, SLOT(resolve()));
+ return;
+}
+
+
+
+void DOCConduit::resolve() {
+ FUNCTIONSETUP;
+
+ for (fSyncInfoListIterator=fSyncInfoList.begin(); fSyncInfoListIterator!=fSyncInfoList.end(); ++fSyncInfoListIterator) {
+ // Walk through each database and apply the conflictResolution option.
+ // the remaining conflicts will be resolved in the resolution dialog
+ if ((*fSyncInfoListIterator).direction==eSyncConflict){
+#ifdef DEBUG
+ DEBUGKPILOT<<"We have a conflict for "<<(*fSyncInfoListIterator).handheldDB<<", default="<<eConflictResolution<<endl;
+#endif
+ switch (eConflictResolution)
+ {
+ case eSyncPDAToPC:
+#ifdef DEBUG
+ DEBUGKPILOT<<"PDA overrides for database "<<(*fSyncInfoListIterator).handheldDB<<endl;
+#endif
+ (*fSyncInfoListIterator).direction = eSyncPDAToPC;
+ break;
+ case eSyncPCToPDA:
+#ifdef DEBUG
+ DEBUGKPILOT<<"PC overrides for database "<<(*fSyncInfoListIterator).handheldDB<<endl;
+#endif
+ (*fSyncInfoListIterator).direction = eSyncPCToPDA;
+ break;
+ case eSyncNone:
+#ifdef DEBUG
+ DEBUGKPILOT<<"No sync for database "<<(*fSyncInfoListIterator).handheldDB<<endl;
+#endif
+ (*fSyncInfoListIterator).direction = eSyncNone;
+ break;
+ case eSyncDelete:
+ case eSyncConflict:
+ default:
+#ifdef DEBUG
+ DEBUGKPILOT<<"Conflict remains due to default resolution setting for database "<<(*fSyncInfoListIterator).handheldDB<<endl;
+#endif
+ break;
+ }
+ }
+ }
+
+ // Show the conflict resolution dialog and ask for the action for each database
+ ResolutionDialog*dlg=new ResolutionDialog( 0, i18n("Conflict Resolution"), &fSyncInfoList , fHandle);
+ bool show=DOCConduitSettings::alwaysShowResolutionDialog() || (dlg && dlg->hasConflicts);
+ if (show) {
+ if (!dlg || !dlg->exec() ) {
+ KPILOT_DELETE(dlg)
+ emit logMessage(i18n("Sync aborted by user."));
+ QTimer::singleShot(0, this, SLOT(cleanup()));
+ return;
+ }
+ }
+ KPILOT_DELETE(dlg)
+
+
+ // fDBNames will be filled with the names of the databases that are actually synced (not deleted), so I can write the list to the config file
+ fDBNames.clear();
+ fSyncInfoListIterator=fSyncInfoList.begin();
+ QTimer::singleShot(0,this, SLOT(syncDatabases()));
+ return;
+}
+
+
+
+void DOCConduit::syncDatabases() {
+ FUNCTIONSETUP;
+ if (fSyncInfoListIterator==fSyncInfoList.end()) {
+ // We're done, so clean up
+ QTimer::singleShot(0, this, SLOT(cleanup()));
+ return;
+ }
+
+ docSyncInfo sinfo=(*fSyncInfoListIterator);
+ ++fSyncInfoListIterator;
+
+ switch (sinfo.direction) {
+ case eSyncConflict:
+#ifdef DEBUG
+ DEBUGKPILOT<<"Entry "<<sinfo.handheldDB<<"( txtfilename: "<<sinfo.txtfilename<<
+ ", pdbfilename: "<<sinfo.pdbfilename<<") had sync direction eSyncConflict!!!"<<endl;
+#endif
+ break;
+ case eSyncDelete:
+ case eSyncPDAToPC:
+ case eSyncPCToPDA:
+ emit logMessage(i18n("Synchronizing text \"%1\"").arg(sinfo.handheldDB));
+ if (!doSync(sinfo)) {
+ // The sync could not be done, so inform the user (the error message should probably issued inside doSync)
+#ifdef DEBUG
+ DEBUGKPILOT<<"There was some error syncing the text \""<<sinfo.handheldDB<<"\" with the file "<<sinfo.txtfilename<<endl;
+#endif
+ }
+ break;
+ case eSyncNone:
+// case eSyncAll:
+ break;
+ }
+ if (sinfo.direction != eSyncDelete) fDBNames.append(sinfo.handheldDB);
+
+ QTimer::singleShot(0,this, SLOT(syncDatabases()));
+ return;
+}
+
+
+PilotDatabase*DOCConduit::openDOCDatabase(const QString &dbname) {
+ if (DOCConduitSettings::localSync())
+ {
+ return new PilotLocalDatabase(DOCConduitSettings::pDBDirectory(), dbname, false);
+ }
+ else
+ {
+ return deviceLink()->database( dbname );
+ }
+}
+
+
+bool DOCConduit::needsSync(docSyncInfo &sinfo)
+{
+ FUNCTIONSETUP;
+ sinfo.direction = eSyncNone;
+
+ PilotDatabase*docdb=openDOCDatabase(QString::fromLatin1(sinfo.dbinfo.name));
+ if (!fDBListSynced.contains(sinfo.handheldDB)) {
+ // the database wasn't included on last sync, so it has to be new.
+#ifdef DEBUG
+ DEBUGKPILOT<<"Database "<<sinfo.dbinfo.name<<" wasn't included in the previous sync!"<<endl;
+#endif
+
+ /* Resolution Table:
+ PC HH | normal PC->HH HH->PC
+ -----------------------------------------
+ N - | P P D
+ - N | H D H
+ N N | C P H
+ */
+
+ if (QFile::exists(sinfo.txtfilename)) sinfo.fPCStatus=eStatNew;
+ else sinfo.fPCStatus=eStatDoesntExist;
+ if (docdb && docdb->isOpen()) sinfo.fPalmStatus=eStatNew;
+ else sinfo.fPalmStatus=eStatDoesntExist;
+ KPILOT_DELETE(docdb);
+
+ switch (eSyncDirection) {
+ case eSyncPDAToPC:
+ if (sinfo.fPalmStatus==eStatDoesntExist)
+ sinfo.direction=eSyncDelete;
+ else sinfo.direction=eSyncPDAToPC;
+ break;
+ case eSyncPCToPDA:
+ if (sinfo.fPCStatus==eStatDoesntExist)
+ sinfo.direction=eSyncDelete;
+ else sinfo.direction=eSyncPCToPDA;
+ break;
+ case eSyncNone: // means actually both directions!
+ if (sinfo.fPCStatus==eStatNew) {
+ if (sinfo.fPalmStatus==eStatNew) sinfo.direction=eSyncConflict;
+ else sinfo.direction=eSyncPCToPDA;
+ } else {
+ if (sinfo.fPalmStatus==eStatNew) sinfo.direction=eSyncPDAToPC;
+ else {
+ sinfo.direction=eSyncNone;
+#ifdef DEBUG
+ DEBUGKPILOT<<"I'm supposed to find a sync direction, but the "<<
+ " text "<<sinfo.dbinfo.name<<" doesn't exist on either "<<
+ " the handheld or the PC"<<endl;
+#endif
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ return true;
+ }
+
+ // Text was included in the last sync
+ if (!QFile::exists(sinfo.txtfilename)) sinfo.fPCStatus=eStatDeleted;
+ else if(pcTextChanged(sinfo.txtfilename)) {
+ sinfo.fPCStatus=eStatChanged;
+#ifdef DEBUG
+ DEBUGKPILOT<<"PC side has changed!"<<endl;
+#endif
+ // TODO: Check for changed bookmarks on the PC side
+#ifdef DEBUG
+ } else {
+ DEBUGKPILOT<<"PC side has NOT changed!"<<endl;
+#endif
+ }
+
+ if (!docdb || !docdb->isOpen()) sinfo.fPalmStatus=eStatDeleted;
+ else if (hhTextChanged(docdb)) {
+#ifdef DEBUG
+ DEBUGKPILOT<<"Handheld side has changed!"<<endl;
+#endif
+ sinfo.fPalmStatus=eStatChanged;
+#ifdef DEBUG
+ } else {
+ DEBUGKPILOT<<"Handheld side has NOT changed!"<<endl;
+#endif
+ }
+ KPILOT_DELETE(docdb);
+
+
+ // Now that we know the status of both sides, determine what to do.
+ /* Resolution Table:
+ PC HH | normal PC->HH HH->PC
+ -----------------------------------------
+ - - | - - -
+ C - | P P H
+ - C | H P H
+ C C | C P H
+ D - | D D H
+ - D | D P D
+ D D | D D D
+ -----------------------------------------
+ C D | C P D
+ D C | C D H
+ */
+
+
+ if (sinfo.fPCStatus == eStatNone && sinfo.fPalmStatus==eStatNone) {
+#ifdef DEBUG
+ DEBUGKPILOT<<"Nothing has changed, not need for a sync."<<endl;
+#endif
+ sinfo.direction=eSyncNone;
+ return false;
+ }
+
+ // In all other cases, if only one direction (PC->HH or HH->PC)
+ // should be done, check if the DB was deleted or if we are supposed
+ // to sync that direction
+
+ if (eSyncDirection==eSyncPCToPDA) {
+ if (sinfo.fPCStatus==eStatDeleted) sinfo.direction=eSyncDelete;
+ else sinfo.direction=eSyncPCToPDA;
+ return true;
+ }
+ if (eSyncDirection==eSyncPDAToPC) {
+ if (sinfo.fPalmStatus==eStatDeleted) sinfo.direction=eSyncDelete;
+ else sinfo.direction=eSyncPDAToPC;
+ return true;
+ }
+
+
+ // ---------------------------------------------------------------
+ // Finally, do the normal case, where both directions are possible
+ // ---------------------------------------------------------------
+
+
+ // if either is deleted, and the other is not changed, delete
+ if ( ((sinfo.fPCStatus==eStatDeleted) && (sinfo.fPalmStatus!=eStatChanged)) ||
+ ((sinfo.fPalmStatus==eStatDeleted) && (sinfo.fPCStatus!=eStatChanged)) )
+ {
+#ifdef DEBUG
+ DEBUGKPILOT<<"DB was deleted on one side and not changed on "
+ "the other -> Delete it."<<endl;
+#endif
+ sinfo.direction=eSyncDelete;
+ return true;
+ }
+
+ // eStatDeleted (and both not changed) have already been treated, for all
+ // other values in combination with eStatNone, just copy the texts.
+ if (sinfo.fPCStatus==eStatNone) {
+#ifdef DEBUG
+ DEBUGKPILOT<<"PC side has changed!"<<endl;
+#endif
+ sinfo.direction=eSyncPDAToPC;
+ return true;
+ }
+
+ if (sinfo.fPalmStatus==eStatNone) {
+ sinfo.direction=eSyncPCToPDA;
+ return true;
+ }
+
+ // All other cases
+ // (deleted,changed), (changed, deleted), (changed,changed)
+ // create a conflict:
+ sinfo.direction=eSyncConflict;
+ return true;
+}
+
+
+
+PilotDatabase *DOCConduit::preSyncAction(docSyncInfo &sinfo) const
+{
+ FUNCTIONSETUP;
+
+ {
+ // make sure the dir for the local texts really exists!
+ QDir dir( DOCConduitSettings::tXTDirectory() );
+ if (!dir.exists())
+ {
+ dir.mkdir(dir.absPath());
+ }
+ }
+
+ DBInfo dbinfo=sinfo.dbinfo;
+ switch (sinfo.direction)
+ {
+ case eSyncPDAToPC:
+ if (DOCConduitSettings::keepPDBsLocally())
+ {
+ // make sure the dir for the local db really exists!
+ QDir dir(DOCConduitSettings::pDBDirectory());
+
+ if (!dir.exists())
+ {
+ dir.mkdir(dir.absPath());
+ }
+#ifdef DEBUG
+ DEBUGKPILOT<<"Need to fetch database "<<dbinfo.name<<
+ " to the directory "<<dir.absPath()<<endl;
+#endif
+ dbinfo.flags &= ~dlpDBFlagOpen;
+
+ if (!fHandle->retrieveDatabase(sinfo.pdbfilename, &dbinfo) )
+ {
+ WARNINGKPILOT << "Unable to retrieve database " << dbinfo.name <<
+ " from the handheld into " << sinfo.pdbfilename << "." << endl;
+ return 0L;
+ }
+ }
+ break;
+ case eSyncPCToPDA:
+ if (DOCConduitSettings::keepPDBsLocally())
+ {
+ // make sure the dir for the local db really exists!
+ QDir dir(DOCConduitSettings::pDBDirectory());
+ if (!dir.exists())
+ {
+ dir.mkdir(dir.absPath());
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ if (DOCConduitSettings::keepPDBsLocally())
+ {
+ return new PilotLocalDatabase(DOCConduitSettings::pDBDirectory(),
+ QString::fromLatin1(dbinfo.name), false);
+ }
+ else
+ {
+ return deviceLink()->database(QString::fromLatin1(dbinfo.name));
+ }
+}
+
+
+// res gives us information whether the sync worked and the db might need to be
+// transferred to the handheld or not (and we just need to clean up the mess)
+bool DOCConduit::postSyncAction(PilotDatabase * database,
+ docSyncInfo &sinfo, bool res)
+{
+ FUNCTIONSETUP;
+ bool rs = true;
+
+ switch (sinfo.direction)
+ {
+ case eSyncPDAToPC:
+ // also reset the sync flags on the handheld
+#ifdef DEBUG
+ DEBUGKPILOT<<"Resetting sync flags for database "
+ <<sinfo.dbinfo.name<<endl;
+#endif
+ if (DOCConduitSettings::keepPDBsLocally() && !DOCConduitSettings::localSync())
+ {
+ PilotDatabase*db=deviceLink()->database(
+ QString::fromLatin1(sinfo.dbinfo.name));
+#ifdef DEBUG
+ DEBUGKPILOT<<"Middle 1 Resetting sync flags for database "
+ <<sinfo.dbinfo.name<<endl;
+#endif
+ if (db)
+ {
+ db->resetSyncFlags();
+ KPILOT_DELETE(db);
+ }
+ }
+#ifdef DEBUG
+ DEBUGKPILOT<<"End Resetting sync flags for database "
+ <<sinfo.dbinfo.name<<endl;
+#endif
+ break;
+ case eSyncPCToPDA:
+ if (DOCConduitSettings::keepPDBsLocally() && !DOCConduitSettings::localSync() && res)
+ {
+ // Copy the database to the palm
+ PilotLocalDatabase*localdb=dynamic_cast<PilotLocalDatabase*>(database);
+ if (localdb)
+ {
+#ifdef DEBUG
+ DEBUGKPILOT<<"Installing file "<<localdb->dbPathName()<<" ("
+ <<sinfo.handheldDB<<") to the handheld"<<endl;
+#endif
+ QString dbpathname=localdb->dbPathName();
+ // This deletes localdb as well, which is just a cast from database
+ KPILOT_DELETE(database);
+ if (!fHandle->installFiles(dbpathname, false))
+ {
+ rs = false;
+#ifdef DEBUG
+ DEBUGKPILOT<<"Could not install the database "<<dbpathname<<" ("
+ <<sinfo.handheldDB<<")"<<endl;
+#endif
+ }
+ }
+ }
+ default:
+ break;
+ }
+
+#ifdef DEBUG
+ DEBUGKPILOT<<"Vor KPILOT_DELETE(database)"<<endl;
+#endif
+
+ KPILOT_DELETE(database);
+#ifdef DEBUG
+ DEBUGKPILOT<<"End postSyncAction"<<endl;
+#endif
+ return rs;
+}
+
+
+
+void DOCConduit::cleanup()
+{
+ FUNCTIONSETUP;
+ DOCConduitSettings::setConvertedDOCfiles( fDBNames );
+ DOCConduitSettings::self()->writeConfig();
+
+ emit syncDone(this);
+}
+
diff --git a/kpilot/conduits/docconduit/doc-conduit.h b/kpilot/conduits/docconduit/doc-conduit.h
new file mode 100644
index 000000000..834002bea
--- /dev/null
+++ b/kpilot/conduits/docconduit/doc-conduit.h
@@ -0,0 +1,152 @@
+#ifndef _doc_CONDUIT_H
+#define _doc_CONDUIT_H
+/* doc-conduit.h KPilot
+**
+** Copyright (C) 2002-2003 by Reinhold Kainhofer
+**
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+
+#include <plugin.h>
+
+class docSyncInfo;
+typedef QValueList<docSyncInfo> syncInfoList;
+
+typedef enum eSyncDirectionEnum {
+ eSyncNone,
+// eSyncAll,
+ eSyncPDAToPC,
+ eSyncPCToPDA,
+ eSyncDelete,
+ eSyncConflict
+ };
+typedef enum eTextStatus {
+ eStatNone=0,
+ eStatNew=1,
+ eStatChanged=2,
+ eStatBookmarksChanged=4,
+ eStatDeleted=8,
+ eStatDoesntExist=16
+ };
+
+
+QString dirToString(eSyncDirectionEnum dir);
+
+class DOCConduit:public ConduitAction {
+Q_OBJECT
+public:
+ eSyncDirectionEnum eSyncDirection;
+
+public:
+ DOCConduit(KPilotLink * o,
+ const char *n = 0L, const QStringList & a = QStringList());
+ virtual ~ DOCConduit();
+
+ bool encode(QStringList fileName, PilotDatabase * db);
+ bool decode(PilotDatabase * db, QString fileName);
+ virtual bool exec();
+protected:
+ virtual bool isCorrectDBTypeCreator(DBInfo dbinfo);
+ virtual const unsigned long dbtype();
+ virtual const unsigned long dbcreator();
+
+public slots:
+/** syncNextDB walks through all PalmDoc databases on the handheld and decides if they are supposed to be synced to the PC.
+ * syncNextDB and syncNextDOC fist build the list of all PalmDoc texts, and then the method syncDatabases does the actual sync. */
+ void syncNextDB();
+ void syncNextTXT();
+ void checkPDBFiles();
+ void checkDeletedDocs();
+ void resolve();
+ void syncDatabases();
+ void cleanup();
+
+ private:
+ /**
+ * Read the global KPilot config file for settings
+ * particular to the docConduit conduit.
+ */
+ void readConfig();
+
+ /**
+ * Check if the database needs to be synced at all.
+ */
+ bool needsSync(docSyncInfo &sinfo);
+ /**
+ * If necessary, copy the database from the palm to a local dir.
+ * Also initialize the docDBInfo that will be passed to the docconverter
+ */
+ PilotDatabase *preSyncAction(docSyncInfo &sinfo) const;
+
+ bool doSync(docSyncInfo &sinfo);
+ /**
+ * Clean up after the sync. The bool parameter res tells
+ * the function if the conversion was successful or not
+ */
+ bool postSyncAction(PilotDatabase * dbinfo, docSyncInfo &sinfo, bool res = true);
+
+ bool pcTextChanged(QString txtfn);
+ bool hhTextChanged(PilotDatabase*docdb);
+
+ /** Opens the database with name dbname. For a local sync, this will be a
+ * PilotLocalDatabase, otherwise it will be a database on the serial device
+ * (i.e. an object of class PilotSerialDatabase) */
+ PilotDatabase *openDOCDatabase(const QString &dbname);
+
+ QString constructPDBFileName(QString name);
+ QString constructTXTFileName(QString name);
+
+ eSyncDirectionEnum eConflictResolution;
+ int fTXTBookmarks, fPDBBookmarks;
+ QStringList fDBListSynced;
+ QStringList fDBNames;
+ syncInfoList fSyncInfoList;
+ syncInfoList::Iterator fSyncInfoListIterator;
+ long int dbnr;
+
+ QStringList docnames;
+ QStringList::Iterator dociterator;
+};
+
+class docSyncInfo
+{
+public:
+ docSyncInfo(QString hhDB=QString(), QString txtfn=QString(), QString pdbfn=QString(), eSyncDirectionEnum dir=eSyncNone)
+ {
+ handheldDB=hhDB;
+ txtfilename=txtfn;
+ pdbfilename=pdbfn;
+ direction=dir;
+ fPCStatus=eStatNone;
+ fPalmStatus=eStatNone;
+ };
+ ~docSyncInfo(){};
+ QString handheldDB, txtfilename, pdbfilename;
+ DBInfo dbinfo;
+ eSyncDirectionEnum direction;
+ eTextStatus fPCStatus, fPalmStatus;
+};
+
+
+#endif
diff --git a/kpilot/conduits/docconduit/doc-conflictdialog.cc b/kpilot/conduits/docconduit/doc-conflictdialog.cc
new file mode 100644
index 000000000..7dafd9b66
--- /dev/null
+++ b/kpilot/conduits/docconduit/doc-conflictdialog.cc
@@ -0,0 +1,182 @@
+/* KPilot
+**
+** Copyright (C) 2002 by Reinhold Kainhofer
+**
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include "options.h"
+#include "doc-conflictdialog.moc"
+
+#include <qlabel.h>
+#include <qpushbutton.h>
+#include <qlayout.h>
+#include <qbuttongroup.h>
+#include <kmessagebox.h>
+#include <qtimer.h>
+#include <qtable.h>
+#include <qcombobox.h>
+#include <qscrollview.h>
+
+
+ResolutionDialog::ResolutionDialog( QWidget* parent, const QString& caption, syncInfoList*sinfo, KPilotLink*lnk )
+ : KDialogBase( parent, "resolutionDialog", true, caption, KDialogBase::Ok|KDialogBase::Cancel, KDialogBase::Ok, true), tickleTimer(0L), fHandle(lnk) {
+ FUNCTIONSETUP;
+ syncInfo=sinfo;
+ hasConflicts=false;
+
+ QWidget *page = new QWidget( this );
+ setMainWidget(page);
+ QVBoxLayout *topLayout = new QVBoxLayout( page, 0, spacingHint() );
+
+ // First, insert the texts on top:
+ textLabel1 = new QLabel(i18n("Here is a list of all text files and DOC databases the conduit found. The conduit tried to determine the correct sync direction, but for databases in bold red letters a conflict occurred (i.e. the text was changed both on the desktop and on the handheld). For these databases please specify which version is the current one."), page);
+ textLabel1->setAlignment( int( QLabel::WordBreak | QLabel::AlignVCenter ) );
+ topLayout->addWidget(textLabel1);
+
+ textLabel2 = new QLabel(i18n("You can also change the sync direction for databases without a conflict." ), page );
+ textLabel2->setAlignment( int( QLabel::WordBreak | QLabel::AlignVCenter ) );
+ topLayout->addWidget(textLabel2);
+
+ resolutionGroupBox = new QGroupBox(i18n("DOC Databases"), page );
+ QVBoxLayout*playout = new QVBoxLayout(resolutionGroupBox);
+ QScrollView* sv = new QScrollView(resolutionGroupBox);
+ playout->addWidget(sv);
+ sv->setResizePolicy(QScrollView::AutoOneFit);
+ sv->setHScrollBarMode(QScrollView::AlwaysOff);
+ sv->setMargin(5);
+ QFrame* big_box = new QFrame(sv->viewport());
+ sv->addChild(big_box);
+
+
+ resolutionGroupBoxLayout = new QGridLayout( big_box, syncInfo->size(), 3 );
+ resolutionGroupBoxLayout->setAlignment( Qt::AlignTop );
+
+ // Invisible button group for the information buttons to use the same slot for all of them (see Dallheimer's book, page 309f)
+ QButtonGroup *bgroup = new QButtonGroup( this );
+ bgroup->hide();
+ QObject::connect(bgroup, SIGNAL(clicked(int)), this, SLOT(slotInfo(int)));
+
+ if (syncInfo) {
+ DEBUGKPILOT<<"Adding resolution options for the databases "<<endl;
+ syncInfoList::Iterator it;
+ int nr=0;
+ DEBUGKPILOT<<"We're having "<<(*syncInfo).size()<<" entries in the database list"<<endl;
+ for (it=syncInfo->begin(); it!=syncInfo->end(); ++it ) {
+ docSyncInfo si=(*it);
+ conflictEntry cE;
+ cE.index=nr;
+ cE.conflict=(si.direction==eSyncConflict);
+ DEBUGKPILOT<<"Adding "<<si.handheldDB<<" to the conflict resolution dialog"<<endl;
+
+ QString text=si.handheldDB;
+ if (cE.conflict) {
+ text=CSL1("<qt><b><font color=red>")+text+CSL1("</font></b></qt>");
+ DEBUGKPILOT<<"We have a conflict for database "<<si.handheldDB<<endl;
+ hasConflicts=true;
+ }
+ cE.dbname=new QLabel(text, big_box);
+ resolutionGroupBoxLayout->addWidget( cE.dbname, cE.index, 0 );
+
+ cE.resolution=new QComboBox( FALSE, big_box);
+ cE.resolution->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)7,
+ (QSizePolicy::SizeType)0, 0, 0,
+ cE.resolution->sizePolicy().hasHeightForWidth() ) );
+ cE.resolution->clear();
+ cE.resolution->insertItem( i18n( "No Sync" ) );
+ cE.resolution->insertItem( i18n( "Sync Handheld to PC" ) );
+ cE.resolution->insertItem( i18n( "Sync PC to Handheld" ) );
+ cE.resolution->insertItem( i18n( "Delete Both Databases" ) );
+ cE.resolution->setCurrentItem((int)si.direction);
+ resolutionGroupBoxLayout->addWidget( cE.resolution, cE.index, 1);
+
+ cE.info = new QPushButton( i18n("More Info..."), big_box );
+ resolutionGroupBoxLayout->addWidget(cE.info, cE.index, 2);
+ bgroup->insert(cE.info);
+
+ conflictEntries.append(cE);
+ ++nr;
+ }
+ } else {
+ WARNINGKPILOT << "The list of text files is not available to the resolution dialog." << endl;
+ }
+
+
+ topLayout->addWidget( resolutionGroupBox );
+ resize( QSize(600, 480).expandedTo(minimumSizeHint()) );
+
+ if (fHandle) tickleTimer=new QTimer(this, "TickleTimer");
+ if (tickleTimer) {
+ connect( tickleTimer, SIGNAL(timeout()), this, SLOT(_tickle()) );
+ tickleTimer->start( 10000 ); // tickle the palm every 10 seconds to prevent a timeout until the sync is really finished.
+ }
+
+}
+
+/*
+ * Destroys the object and frees any allocated resources
+ */
+ResolutionDialog::~ResolutionDialog()
+{
+ // no need to delete child widgets, Qt does it all for us
+}
+
+/* virtual slot */ void ResolutionDialog::slotOk() {
+ FUNCTIONSETUP;
+ QValueList<conflictEntry>::Iterator ceIt;
+ for (ceIt=conflictEntries.begin(); ceIt!=conflictEntries.end(); ++ceIt) {
+ (*syncInfo)[(*ceIt).index].direction=(eSyncDirectionEnum)((*ceIt).resolution->currentItem());
+ }
+ KDialogBase::slotOk();
+}
+
+QString eTextStatusToString(eTextStatus stat) {
+ switch(stat) {
+ case eStatNone: return i18n("unchanged");
+ case eStatNew: return i18n("new");
+ case eStatChanged: return i18n("changed");
+ case eStatBookmarksChanged: return i18n("only bookmarks changed");
+ case eStatDeleted: return i18n("deleted");
+ case eStatDoesntExist: return i18n("does not exist");
+ default: return i18n("unknown");
+ }
+}
+
+void ResolutionDialog::slotInfo(int index) {
+ FUNCTIONSETUP;
+ conflictEntry cE=conflictEntries[index];
+ int ix=cE.index;
+ if (!syncInfo) return;
+ docSyncInfo si=(*syncInfo)[ix];
+ QString text=i18n("Status of the database %1:\n\n").arg(si.handheldDB);
+ text+=i18n("Handheld: %1\n").arg(eTextStatusToString(si.fPalmStatus));
+ text+=i18n("Desktop: %1\n").arg(eTextStatusToString(si.fPCStatus));
+
+ KMessageBox::information(this, text, i18n("Database information"));
+}
+
+
+void ResolutionDialog::_tickle() {
+ FUNCTIONSETUP;
+ if (fHandle) fHandle->tickle();
+}
diff --git a/kpilot/conduits/docconduit/doc-conflictdialog.h b/kpilot/conduits/docconduit/doc-conflictdialog.h
new file mode 100644
index 000000000..f8ad8caf7
--- /dev/null
+++ b/kpilot/conduits/docconduit/doc-conflictdialog.h
@@ -0,0 +1,83 @@
+#ifndef CONFLICTDIALOG_H
+#define CONFLICTDIALOG_H
+/* doc-conflictdialog.h KPilot
+**
+** Copyright (C) 2002-2003 by Reinhold Kainhofer
+**
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+
+#include <kdialogbase.h>
+#include "doc-conduit.h"
+
+
+class QComboBox;
+class QGridLayout;
+class QGroupBox;
+
+class QLabel;
+class QPushButton;
+class QTimer;
+class KPilotLink;
+
+
+typedef struct conflictEntry {
+ QLabel*dbname;
+ QComboBox* resolution;
+ QPushButton*info;
+ int index;
+ bool conflict;
+};
+
+
+class ResolutionDialog : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+ ResolutionDialog( QWidget* parent=0, const QString& caption=i18n("Resolution Dialog"), syncInfoList*sinfo=0L, KPilotLink*lnk=0L);
+ ~ResolutionDialog();
+
+ bool hasConflicts;
+public slots:
+ void _tickle();
+protected:
+ QTimer* tickleTimer;
+ KPilotLink* fHandle;
+
+protected:
+ QGroupBox* resolutionGroupBox;
+ QGridLayout*resolutionGroupBoxLayout;
+
+ syncInfoList*syncInfo;
+ QValueList<conflictEntry> conflictEntries;
+ QLabel *textLabel1,*textLabel2;
+
+protected slots:
+ virtual void slotOk();
+ void slotInfo(int index);
+
+};
+
+#endif // CONFLICTDIALOG_H
diff --git a/kpilot/conduits/docconduit/doc-factory.cc b/kpilot/conduits/docconduit/doc-factory.cc
new file mode 100644
index 000000000..3d2a16b11
--- /dev/null
+++ b/kpilot/conduits/docconduit/doc-factory.cc
@@ -0,0 +1,116 @@
+/* KPilot
+**
+** Copyright (C) 2002 by Reinhold Kainhofer
+**
+** This file defines the factory for the doc-conduit plugin.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include "options.h"
+#include "doc-factory.moc"
+#include "doc-factory.h"
+
+#include <kinstance.h>
+#include <kaboutdata.h>
+#include <kpilotlink.h>
+
+#include "doc-conduit.h"
+#include "doc-setup.h"
+
+
+extern "C" {
+ void *init_conduit_doc() {
+ return new DOCConduitFactory;
+ }
+}
+
+
+
+// A number of static variables
+KAboutData * DOCConduitFactory::fAbout = 0L;
+
+const char *DOCConduitFactory::dbDOCtype = "TEXt";
+const char *DOCConduitFactory::dbDOCcreator = "REAd";
+
+
+
+DOCConduitFactory::DOCConduitFactory(QObject * p, const char *n):
+KLibFactory(p, n)
+{
+ FUNCTIONSETUP;
+ fInstance = new KInstance("docconduit");
+ fAbout =new KAboutData("docconduit",
+ I18N_NOOP("Palm DOC Conduit for KPilot"), KPILOT_VERSION,
+ I18N_NOOP("Configures the DOC Conduit for KPilot"),
+ KAboutData::License_GPL, "(C) 2002, Reinhold Kainhofer");
+
+ fAbout->addAuthor("Reinhold Kainhofer",
+ I18N_NOOP("Maintainer"), "reinhold@kainhofer.com",
+ "http://reinhold.kainhofer.com");
+}
+
+DOCConduitFactory::~DOCConduitFactory()
+{
+ FUNCTIONSETUP;
+ KPILOT_DELETE(fInstance);
+ KPILOT_DELETE(fAbout);
+}
+
+
+/* virtual */ QObject * DOCConduitFactory::createObject(QObject * p,
+ const char *n, const char *c, const QStringList & a)
+{
+ FUNCTIONSETUP;
+
+#ifdef DEBUG
+ DEBUGKPILOT << fname <<": Creating object of class " <<c <<endl;
+#endif
+ if (qstrcmp(c, "ConduitConfigBase") == 0)
+ {
+ QWidget *w = dynamic_cast<QWidget *>(p);
+ if (w)
+ {
+ return new DOCWidgetConfig(w,n);
+ }
+ else
+ {
+ WARNINGKPILOT << "Couldn't cast parent to widget." << endl;
+ return 0L;
+ }
+ }
+ if (qstrcmp(c, "SyncAction") == 0)
+ {
+ KPilotLink * d = dynamic_cast < KPilotLink * >(p);
+ if (d)
+ {
+ return new DOCConduit(d, n, a);
+ }
+ else
+ {
+ WARNINGKPILOT << "Couldn't cast parent to KPilotLink" <<endl;
+ return 0L;
+ }
+ }
+ return 0L;
+}
+
diff --git a/kpilot/conduits/docconduit/doc-factory.h b/kpilot/conduits/docconduit/doc-factory.h
new file mode 100644
index 000000000..c848777a0
--- /dev/null
+++ b/kpilot/conduits/docconduit/doc-factory.h
@@ -0,0 +1,74 @@
+#ifndef _DOC_FACTORY_H
+#define _DOC_FACTORY_H
+
+/* doc-factory.h KPilot
+**
+** Copyright (C) 2002 by Reinhold Kainhofer
+**
+** This file defines the factory for the doc-conduit plugin.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include <klibloader.h>
+
+class KInstance;
+class KAboutData;
+
+
+class DOCConduitFactory:public KLibFactory
+{
+
+Q_OBJECT
+
+public:
+ DOCConduitFactory(QObject * = 0L, const char * = 0L);
+ virtual ~ DOCConduitFactory();
+
+ static KAboutData *about() {
+ return fAbout;
+ };
+
+ static const char
+ *fDBListSynced;
+ static const char *dbDOCtype;
+ static const char *dbDOCcreator;
+
+
+protected:
+ virtual QObject * createObject(QObject * parent = 0,
+ const char *name = 0,
+ const char *classname = "QObject",
+ const QStringList & args = QStringList());
+
+private:
+ KInstance * fInstance;
+ static KAboutData *fAbout;
+};
+
+
+extern "C" {
+ void *init_libdocconduit();
+}
+
+
+#endif
diff --git a/kpilot/conduits/docconduit/doc-setup.cc b/kpilot/conduits/docconduit/doc-setup.cc
new file mode 100644
index 000000000..a6de2d2ad
--- /dev/null
+++ b/kpilot/conduits/docconduit/doc-setup.cc
@@ -0,0 +1,136 @@
+/* KPilot
+**
+** Copyright (C) 2002 by Reinhold Kainhofer
+**
+** This file defines the setup dialog for the doc-conduit plugin.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include "options.h"
+
+#include <qtabwidget.h>
+#include <qcheckbox.h>
+#include <qbuttongroup.h>
+#include <qcombobox.h>
+
+#include <kconfig.h>
+#include <kurlrequester.h>
+#include <kcharsets.h>
+
+#include "doc-setupdialog.h"
+#include "doc-factory.h"
+#include "doc-setup.h"
+#include "docconduitSettings.h"
+
+
+DOCWidgetConfig::DOCWidgetConfig(QWidget * w, const char *n):
+ ConduitConfigBase(w, n),
+ fConfigWidget(new DOCWidget(w))
+{
+ FUNCTIONSETUP;
+
+ fWidget=fConfigWidget;
+
+ QStringList l = KGlobal::charsets()->descriptiveEncodingNames();
+ for ( QStringList::Iterator it = l.begin(); it != l.end(); ++it)
+ {
+ fConfigWidget->fEncoding->insertItem(*it);
+ }
+
+ fConfigWidget->fTXTDir->setMode(KFile::Directory);
+ fConfigWidget->fPDBDir->setMode(KFile::Directory);
+ ConduitConfigBase::addAboutPage(fConfigWidget->tabWidget,DOCConduitFactory::about());
+
+ fConduitName=i18n("Palm DOC");
+
+#define CMOD(a,b) connect(fConfigWidget->a,SIGNAL(b),this,SLOT(modified()))
+ CMOD(fTXTDir,textChanged(const QString &));
+ CMOD(fPDBDir,textChanged(const QString &));
+ CMOD(fkeepPDBLocally,clicked());
+ CMOD(fConflictResolution,clicked(int));
+ CMOD(fConvertBookmarks,stateChanged(int));
+ CMOD(fBookmarksBmk,stateChanged(int));
+ CMOD(fBookmarksInline,stateChanged(int));
+ CMOD(fBookmarksEndtags,stateChanged(int));
+ CMOD(fCompress,stateChanged(int));
+ CMOD(fSyncDirection,clicked(int));
+ CMOD(fNoConversionOfBmksOnly,stateChanged(int));
+ CMOD(fAlwaysUseResolution,stateChanged(int));
+ CMOD(fPCBookmarks,clicked(int));
+ CMOD(fEncoding,textChanged(const QString &));
+#undef CMOD
+
+ fConfigWidget->adjustSize();
+}
+
+/* virtual */ void DOCWidgetConfig::commit()
+{
+ FUNCTIONSETUP;
+
+ DOCConduitSettings::setTXTDirectory( fConfigWidget->fTXTDir->url() );
+ DOCConduitSettings::setPDBDirectory( fConfigWidget->fPDBDir->url() );
+
+ DOCConduitSettings::setKeepPDBsLocally( fConfigWidget->fkeepPDBLocally->isChecked());
+ DOCConduitSettings::setConflictResolution( fConfigWidget->fConflictResolution->id(
+ fConfigWidget->fConflictResolution->selected()) );
+ DOCConduitSettings::setConvertBookmarks(fConfigWidget->fConvertBookmarks->isChecked());
+ DOCConduitSettings::setBmkFileBookmarks(fConfigWidget->fBookmarksBmk->isChecked());
+ DOCConduitSettings::setInlineBookmarks(fConfigWidget->fBookmarksInline->isChecked());
+ DOCConduitSettings::setEndtagBookmarks(fConfigWidget->fBookmarksEndtags->isChecked());
+ DOCConduitSettings::setCompress(fConfigWidget->fCompress->isChecked());
+ DOCConduitSettings::setSyncDirection(fConfigWidget->fSyncDirection->id(
+ fConfigWidget->fSyncDirection->selected()));
+ DOCConduitSettings::setIgnoreBmkChanges(fConfigWidget->fNoConversionOfBmksOnly->isChecked());
+ DOCConduitSettings::setAlwaysShowResolutionDialog(fConfigWidget->fAlwaysUseResolution->isChecked());
+ DOCConduitSettings::setBookmarksToPC( fConfigWidget->fPCBookmarks->id(
+ fConfigWidget->fPCBookmarks->selected()) );
+ DOCConduitSettings::setEncoding( fConfigWidget->fEncoding->currentText() );
+
+ DOCConduitSettings::self()->writeConfig();
+ unmodified();
+}
+
+/* virtual */ void DOCWidgetConfig::load()
+{
+ FUNCTIONSETUP;
+ DOCConduitSettings::self()->readConfig();
+
+ fConfigWidget->fTXTDir->setURL( DOCConduitSettings::tXTDirectory() );
+ fConfigWidget->fPDBDir->setURL( DOCConduitSettings::pDBDirectory() );
+ fConfigWidget->fkeepPDBLocally->setChecked( DOCConduitSettings::keepPDBsLocally() );
+ fConfigWidget->fConflictResolution->setButton(DOCConduitSettings::conflictResolution() );
+ fConfigWidget->fConvertBookmarks->setChecked(DOCConduitSettings::convertBookmarks() );
+ fConfigWidget->fBookmarksBmk->setChecked(DOCConduitSettings::bmkFileBookmarks() );
+ fConfigWidget->fBookmarksInline->setChecked(DOCConduitSettings::inlineBookmarks() );
+ fConfigWidget->fBookmarksEndtags->setChecked(DOCConduitSettings::endtagBookmarks() );
+ fConfigWidget->fCompress->setChecked(DOCConduitSettings::compress() );
+ fConfigWidget->fSyncDirection->setButton(DOCConduitSettings::syncDirection() );
+
+ fConfigWidget->fNoConversionOfBmksOnly->setChecked( DOCConduitSettings::ignoreBmkChanges() );
+ fConfigWidget->fAlwaysUseResolution->setChecked( DOCConduitSettings::alwaysShowResolutionDialog() );
+
+ fConfigWidget->fPCBookmarks->setButton(DOCConduitSettings::bookmarksToPC() );
+ fConfigWidget->fEncoding->setCurrentText(DOCConduitSettings::encoding() );
+ unmodified();
+}
+
diff --git a/kpilot/conduits/docconduit/doc-setup.h b/kpilot/conduits/docconduit/doc-setup.h
new file mode 100644
index 000000000..470585e01
--- /dev/null
+++ b/kpilot/conduits/docconduit/doc-setup.h
@@ -0,0 +1,47 @@
+#ifndef _DOC_DOC_SETUP_H
+#define _DOC_DOC_SETUP_H
+/* doc-setup.h KPilot
+**
+** Copyright (C) 2002 by Reinhold Kainhofer
+**
+** This file defines the widget and behavior for the config dialog
+** of the doc conduit.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include "plugin.h"
+
+class DOCWidget;
+
+class DOCWidgetConfig : public ConduitConfigBase
+{
+public:
+ DOCWidgetConfig(QWidget *, const char *);
+ virtual void commit();
+ virtual void load();
+protected:
+ DOCWidget *fConfigWidget;
+} ;
+
+
+#endif
diff --git a/kpilot/conduits/docconduit/doc-setupdialog.ui b/kpilot/conduits/docconduit/doc-setupdialog.ui
new file mode 100644
index 000000000..cbb45e344
--- /dev/null
+++ b/kpilot/conduits/docconduit/doc-setupdialog.ui
@@ -0,0 +1,557 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>DOCWidget</class>
+<author>Reinhold Kainhofer</author>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>Form2</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>564</width>
+ <height>266</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>3</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QTabWidget" row="0" column="0">
+ <property name="name">
+ <cstring>tabWidget</cstring>
+ </property>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>General</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>TextLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Text files:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>fTXTDir</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Enter here, or select clicking the file picker button, the name and location of the folder used to find and synchronize text files. All files with extension .txt located in this folder will be synced to Palm DOC databases in your handheld.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="1" column="0">
+ <property name="name">
+ <cstring>fkeepPDBLocally</cstring>
+ </property>
+ <property name="text">
+ <string>Local co&amp;py:</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Check this box if you want to save a copy of the Palm DOC databases (.pdb files) on your PC.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="KURLRequester" row="0" column="1">
+ <property name="name">
+ <cstring>fTXTDir</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Enter here, or select clicking the file picker button, the name and location of the folder used to find and synchronize text files. All files with extension .txt located in this folder will be synced to Palm DOC databases in your handheld.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QButtonGroup" row="2" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>fSyncDirection</cstring>
+ </property>
+ <property name="title">
+ <string>Synchronization Mode</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QRadioButton" row="2" column="0">
+ <property name="name">
+ <cstring>RadioButton3</cstring>
+ </property>
+ <property name="text">
+ <string>Sync only P&amp;C to PDA</string>
+ </property>
+ <property name="buttonGroupId">
+ <number>2</number>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Select this option to synchronize texts changed in your PC to Palm DOC databases in your handheld. Palm DOC databases modified in the handheld will not be converted to text files, but texts changed in the PC will be converted to the Palm DOC databases.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="1" column="0">
+ <property name="name">
+ <cstring>RadioButton2</cstring>
+ </property>
+ <property name="text">
+ <string>Sync only P&amp;DA to PC</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Select this option to synchronize the changes made to Palm DOC databases in your handheld to the PC text files. Palm DOC databases modified in the handheld will be converted to text files, but texts changed in the PC will not be converted to the Palm DOC databases.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="0" column="0">
+ <property name="name">
+ <cstring>RadioButton1</cstring>
+ </property>
+ <property name="text">
+ <string>Sync &amp;all</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="buttonGroupId">
+ <number>0</number>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Select this option to synchronize the file texts in your PC to Palm DOC databases in your handheld. Palm DOC databases modified in the handheld will be converted to text files, and texts changed in the PC will be converted to the Palm DOC databases, keeping both versions in sync.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <spacer row="3" column="1">
+ <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>
+ <widget class="KURLRequester" row="1" column="1">
+ <property name="name">
+ <cstring>fPDBDir</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Enter here, or select clicking the file picker button, the name and location of the folder where copies of the handheld databases are kept (.pdb files). Local copies are only made if the box is checked as well.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>PC -&gt; Handheld</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox" row="0" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>fCompress</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Compress</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Check this box, if the text should be compressed on the handheld to save memory. Most doc reader on the handheld support compressed texts.</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;The Palm DOC format supports compressing the text to save memory. Check this box to enable text compression, so the resulting Palm DOC database will consume about 50% less memory than in uncompressed state. Almost all DOC readers on the Palm support compressed texts.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="1" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>fConvertBookmarks</cstring>
+ </property>
+ <property name="text">
+ <string>Convert &amp;bookmarks</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Check this box to enable bookmark creation when converting text files to Palm DOC databases. Most doc readers support bookmarks. In order to create a bookmark, it is necessary to to provide the location in the text where the bookmark should be set and the bookmark title, in at least one of the formats listed below.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <spacer row="6" column="2">
+ <property name="name">
+ <cstring>spacer9</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>
+ <widget class="QCheckBox" row="2" column="1">
+ <property name="name">
+ <cstring>fBookmarksInline</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Inline tags in text</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Check this box to create bookmarks from inline tags in the text. The inline tag consist of tags in the form &lt;* bookmarktext *&gt;. The bookmark location is set using the location of the inline tag in the text, and the name is the text between the &lt;* and the *&gt;. The inline tag (&lt;*...*&gt;) will be removed from the text.</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="5" column="0">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Encoding:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>fEncoding</cstring>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="3" column="1">
+ <property name="name">
+ <cstring>fBookmarksEndtags</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Tags at end of text</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Check this box to convert tags of the form &lt;bookmarkname&gt; at the end of the text to bookmarks. The text inside the tag ("bookmarkname") will be searched in the text, and whenever found, a bookmark will be set there. The endtags &lt;...&gt; will then be removed from the end of the text.</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="4" column="1">
+ <property name="name">
+ <cstring>fBookmarksBmk</cstring>
+ </property>
+ <property name="text">
+ <string>Regular &amp;expressions in .bmk file</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Check this box to use regular expressions in a file to search the text for bookmarks. The file should have the same name as the text file, but should end in .bmk instead of .txt (for instance, the regular expression file for textname.txt should be textname.bmk). See the documentation for a description of the format of the bmk file.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QComboBox" row="5" column="1">
+ <property name="name">
+ <cstring>fEncoding</cstring>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Handheld -&gt; PC</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer row="2" column="0">
+ <property name="name">
+ <cstring>spacer16</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>
+ <widget class="QCheckBox" row="1" column="0">
+ <property name="name">
+ <cstring>fNoConversionOfBmksOnly</cstring>
+ </property>
+ <property name="text">
+ <string>Do not convert, if text unchanged (only bookmarks)</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Check this box to avoid syncing the text on the handheld to the PC if you only changed the bookmarks on the handheld (but not the text).&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QButtonGroup" row="0" column="0">
+ <property name="name">
+ <cstring>fPCBookmarks</cstring>
+ </property>
+ <property name="title">
+ <string>Convert Bookmarks</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QRadioButton" row="0" column="0">
+ <property name="name">
+ <cstring>radioButton8</cstring>
+ </property>
+ <property name="text">
+ <string>Do &amp;not convert bookmarks</string>
+ </property>
+ <property name="buttonGroupId">
+ <number>0</number>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Check this box to avoid converting Palm DOC bookmarks to inline tags or to a bookmark file.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="1" column="0">
+ <property name="name">
+ <cstring>radioButton11</cstring>
+ </property>
+ <property name="text">
+ <string>Convert into .bm &amp;file</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="buttonGroupId">
+ <number>1</number>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Check this box to convert the Palm DOC database bookmarks to a separate file, in the bmk format (see more about this format in the documentation). The resulting bookmark file shares the same filename as the resulting .txt file, but ends in .bmk instead. This approach creates a clean text file and a bookmark file.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="2" column="0">
+ <property name="name">
+ <cstring>radioButton9</cstring>
+ </property>
+ <property name="text">
+ <string>Convert as &amp;inline tags</string>
+ </property>
+ <property name="buttonGroupId">
+ <number>2</number>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Check this box to convert the Palm DOC database bookmarks to inline tags, in the form &amp;lt;* BookmarkName *&amp;gt;. These tags are inserted in the text in the position marked by the bookmark, and the text inside the tag corresponds to the bookmark name. Inline tags are easy to create, delete, move and edit.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Conflicts</string>
+ </attribute>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QButtonGroup">
+ <property name="name">
+ <cstring>fConflictResolution</cstring>
+ </property>
+ <property name="title">
+ <string>Conflict Resolution</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>If the same text was changed on the PC and the handheld, which of the two versions should be used as the new version?</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;The Palm DOC conduit does not feature merging the modifications when a text is changed both in the handheld and in the computer. Therefore, the choice is between working with the files out of sync, or discarding the changes in one of them.&lt;/qt&gt;</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QRadioButton" row="0" column="0">
+ <property name="name">
+ <cstring>radioButton12</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;No resolution</string>
+ </property>
+ <property name="buttonGroupId">
+ <number>0</number>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;The Palm DOC conduit does not feature merging the modifications when a text is changed both in the handheld and in the computer. Therefore, when conflicts appear, the choice is between working with the files out of sync, or discarding the changes in one of them. Select this option to prevent KPilot from overwriting your modifications.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="1" column="0">
+ <property name="name">
+ <cstring>RadioButton5</cstring>
+ </property>
+ <property name="text">
+ <string>P&amp;DA overrides</string>
+ </property>
+ <property name="buttonGroupId">
+ <number>1</number>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;The Palm DOC conduit does not feature merging the modifications when a text is changed both in the handheld and in the computer. Therefore, when conflicts appear, the choice is between working with the files out of sync, or discarding the changes in one of them. Select this option to make the PDA version overwrite the PC version in case of conflict.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="2" column="0">
+ <property name="name">
+ <cstring>RadioButton4</cstring>
+ </property>
+ <property name="text">
+ <string>P&amp;C overrides</string>
+ </property>
+ <property name="buttonGroupId">
+ <number>2</number>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;The Palm DOC conduit does not feature merging the modifications when a text is changed both in the handheld and in the computer. Therefore, when conflicts appear, the choice is between working with the files out of sync, or discarding the changes in one of them. Select this option to make the PC version overwrite the PDA version in case of conflict.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="3" column="0">
+ <property name="name">
+ <cstring>RadioButton7</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Ask the user</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="buttonGroupId">
+ <number>4</number>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;The Palm DOC conduit does not feature merging the modifications when a text is changed both in the handheld and in the computer. Therefore, when conflicts appear, the choice is between working with the files out of sync, or discarding the changes in one of them. Select this option to show the resolution dialog to let the user decide on a case by case basis.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>fAlwaysUseResolution</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Always show the resolution dialog</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Check this box to force the resolution dialog to appear even when there are no conflicts.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>Spacer8</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>
+ </widget>
+ </grid>
+</widget>
+<customwidgets>
+</customwidgets>
+<connections>
+ <connection>
+ <sender>fConvertBookmarks</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>fBookmarksInline</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>fConvertBookmarks</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>fBookmarksEndtags</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>fConvertBookmarks</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>fBookmarksBmk</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>fkeepPDBLocally</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>fPDBDir</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+</connections>
+<tabstops>
+ <tabstop>fTXTDir</tabstop>
+ <tabstop>fkeepPDBLocally</tabstop>
+ <tabstop>fPDBDir</tabstop>
+ <tabstop>fCompress</tabstop>
+ <tabstop>fConvertBookmarks</tabstop>
+ <tabstop>fBookmarksInline</tabstop>
+ <tabstop>fBookmarksEndtags</tabstop>
+ <tabstop>fBookmarksBmk</tabstop>
+ <tabstop>radioButton11</tabstop>
+ <tabstop>fNoConversionOfBmksOnly</tabstop>
+ <tabstop>RadioButton7</tabstop>
+ <tabstop>fAlwaysUseResolution</tabstop>
+ <tabstop>tabWidget</tabstop>
+ <tabstop>RadioButton1</tabstop>
+</tabstops>
+<layoutdefaults spacing="6" margin="11"/>
+<includes>
+ <include location="global" impldecl="in implementation">kurlrequester.h</include>
+ <include location="global" impldecl="in implementation">klineedit.h</include>
+ <include location="global" impldecl="in implementation">kpushbutton.h</include>
+</includes>
+</UI>
diff --git a/kpilot/conduits/docconduit/doc_conduit.desktop b/kpilot/conduits/docconduit/doc_conduit.desktop
new file mode 100644
index 000000000..65f1ce425
--- /dev/null
+++ b/kpilot/conduits/docconduit/doc_conduit.desktop
@@ -0,0 +1,59 @@
+[Desktop Entry]
+Type=Service
+Comment=Adds text files to your handheld, suitable for DOC readers.
+Comment[af]=Voeg teks lêers by jou draagbare toestel in DOC leser formaat.
+Comment[bg]=ДобавÑне на текÑтови файлове към мобилно уÑтройÑтво.
+Comment[ca]=Afegeix fitxers de text a la vostra agenda, apropiat per a lectors de DOC.
+Comment[cs]=PÅ™idává textové soubory do vaÅ¡eho Pilotu, výhodné pro Ätenáře dokumentů.
+Comment[da]=Tilføjer tekstfiler til din håndholdte, passende for DOC-læsere.
+Comment[de]=Gibt Textdateien in Taschencomputer ein, passend für DOC-Leser.
+Comment[el]=ΠÏοσθέτει αÏχεία κειμένου στον υπολογιστή παλάμης σας, κατάλληλο για αναγνώστες DOC.
+Comment[es]=Añade archivos de texto a su agenda electrónica. Compatible con los lectores DOC.
+Comment[et]=Lisab DOC-riiderile sobilikud tekstifailid sinu pihuseadmele.
+Comment[eu]=Zure agenda elektronikora DOC irakurleentzako aproposak diren testu fitxategiak gehitzen ditu.
+Comment[fa]=پرونده‌های متن را به دستی شما اضاÙÙ‡ می‌کند، Ú©Ù‡ برای خوانندگان DOC Ù…Ùید است.
+Comment[fi]=Lisää tekstitiedostoja taskutietokoneeseen. Tämä on käyttökelpoinen DOC-lukijoille.
+Comment[fr]=Ajoute des fichiers texte à votre Palm, approprié pour les lecteurs de DOC.
+Comment[fy]=Heakket tekstfjilden ta oan jo handheld, geskikt faor DOC-lêzers.
+Comment[gl]=Engade ficheiros de texto ao seu aparello de man, axeitado para os lectores DOC.
+Comment[hu]=Szöveges fájlok hozzáadása a kézi számítógéphez, DOC-olvasók számára.
+Comment[is]=Bætir textaskrám, sem hægt er að lesa í DOC lesara, við lófatölvuna þína.
+Comment[it]=Aggiunge file di testo al tuo Pilot, adatti per lettori DOC.
+Comment[ja]=テキストファイルを DOC リーダーã«é©ã—ãŸå½¢å¼ã§ãƒãƒ³ãƒ‰ãƒ˜ãƒ«ãƒ‰ã«è¿½åŠ ã—ã¾ã™ã€‚
+Comment[ka]=უმáƒáƒ¢áƒ”ბს ტექსტურ ფáƒáƒ˜áƒšáƒ”ბს თქვენს პრáƒáƒ¢áƒáƒ¢áƒ˜áƒ£áƒš მáƒáƒ¬áƒ§áƒáƒ‘ილáƒáƒ‘áƒáƒ¡, რáƒáƒ›áƒ”ლიც შესáƒáƒ¤áƒ”რისირDOC წáƒáƒ›áƒ™áƒ˜áƒ—ხáƒáƒ•áƒ”ბისთვის
+Comment[kk]=DOC файлды оқи алатын қалта құрылғыға мәтінді көшіру.
+Comment[km]=បន្ážáŸ‚ម​ឯកសារ​អážáŸ’ážáž”ទ​ទៅ​ឧបករណáŸâ€‹áž™áž½ážšâ€‹ážŠáŸƒâ€‹ážšáž”ស់​អ្នក (សមស្រប​សម្រាប់​កម្មវិធី​អាន DOC) ។
+Comment[lt]=Prideda teksto bylas prie Jūsų nešiojamos knygelės, tinka DOC skaityklėms.
+Comment[ms]=Menambah fail teks ke komputer telapak, sesuai dengan pembaca DOC.
+Comment[nb]=Legger til tekstfiler på PDA-en, som passer for DOC-lesere.
+Comment[nds]=Föögt Textdateien op den Handreekner to, de för DOC-Kiekers passt.
+Comment[ne]=DOC रिडरका लागि उपयà¥à¤•à¥à¤¤ हà¥à¤¨à¥‡ पाठ फाइल तपाईà¤à¤•à¥‹ हà¥à¤¯à¤¾à¤¨à¥à¤¡à¤¹à¥‡à¤²à¥à¤¡à¤®à¤¾ थपà¥à¤¦à¤› ।
+Comment[nl]=Voegt tekstvelden toe aan uw handheld, geschikt voor DOC-lezers.
+Comment[nn]=Legg til tekstfiler på den handhaldne, passar til DOC-lesarar.
+Comment[pl]=Dodaje pliki tekstowe do Twojego palmtopa, w postaci odpowiedniej dla przeglÄ…darek DOC.
+Comment[pt]=Adiciona ficheiros de texto ao seu PDA, indicado para os leitores de DOC.
+Comment[pt_BR]=Adiciona arquivos de texto ao seu handheld, adequado para leitors de DOC.
+Comment[ru]=ÐŸÐµÑ€ÐµÐ½Ð¾Ñ Ñ‚ÐµÐºÑтовых файлов на КПК.
+Comment[sk]=Pridá textové súbory do ruÄného zariadenia, vhodné pre Äítanie DOC.
+Comment[sl]=V vaÅ¡ roÄni raÄunalnik doda besedilne datoteke, primerne za bralnike DOC.
+Comment[sr]=Додаје текÑтуалне фајлове вашем ручном рачунару, погодне за DOC читаче.
+Comment[sr@Latn]=Dodaje tekstualne fajlove vaÅ¡em ruÄnom raÄunaru, pogodne za DOC ÄitaÄe.
+Comment[sv]=Lägger till textfiler i en handdator, lämpliga för DOC-läsare.
+Comment[ta]=DOC படிபà¯à®ªà®µà®°à¯à®•à®³à¯à®•à¯à®•à¯ பொரà¯à®¤à¯à®¤à®®à®¾à®© உஙà¯à®•à®³à¯ பைலடà¯à®Ÿà¯à®•à¯à®•à¯à®°à®¿à®¯ உரை கோபà¯à®ªà¯à®•à®³à¯ˆ சேரà¯à®•à¯à®•à¯à®®à¯
+Comment[tr]=Metin dosyalarını el bilgisayarınıza ekler, DOC biçimi okuyucuları için uygundur.
+Comment[uk]=Додає текÑтові файли до вашого кишенькового приÑтрою так, що вони читатимутьÑÑ Ñƒ переглÑдачах DOC.
+Comment[zh_CN]=将文本文件添加到您的手æŒè®¾å¤‡ä¸­ï¼Œä»¥ä¾¿é€‚åˆ DOC 阅读程åºã€‚
+Comment[zh_TW]=新增文字到您的 handheld。
+Name=Palm DOC
+Name[ca]=DOC de Palm
+Name[cy]=DOC Palm
+Name[de]=Palm-DOC
+Name[fa]=رایانۀ جیبی DOC
+Name[hi]=पॉम डॉक
+Name[nds]=Palm-DOC
+Name[ne]=पालà¥à¤® DOC
+Name[pt]=DOC do Palm
+Name[ta]=பாம௠ஆவணமà¯
+Implemented=file
+ServiceTypes=KPilotConduit
+X-KDE-Library=conduit_doc
diff --git a/kpilot/conduits/docconduit/docconduit.kcfg b/kpilot/conduits/docconduit/docconduit.kcfg
new file mode 100644
index 000000000..6301f4595
--- /dev/null
+++ b/kpilot/conduits/docconduit/docconduit.kcfg
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
+ http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
+ <kcfgfile name="kpilot_docconduitrc"/>
+ <group name="General">
+ <entry name="TXTDirectory" key="TXT Directory" type="Path"/>
+ <entry name="PDBDirectory" key="PDB Directory" type="Path"/>
+ <entry name="KeepPDBsLocally" key="Keep PDBs locally" type="Bool">
+ <default>false</default>
+ </entry>
+ <entry name="LocalSync" key="Sync only locally" type="Bool">
+ <default>false</default>
+ </entry>
+ <entry name="ConflictResolution" key="Conflict Resolution" type="UInt">
+ <default>0</default>
+ </entry>
+ <entry name="ConvertBookmarks" key="Convert Bookmarks" type="Bool">
+ <default>true</default>
+ </entry>
+ <entry name="BmkFileBookmarks" key="Bmk file bookmarks" type="Bool">
+ <default>true</default>
+ </entry>
+ <entry name="InlineBookmarks" key="Inline bookmarks" type="Bool">
+ <default>true</default>
+ </entry>
+ <entry name="EndtagBookmarks" key="Endtag bookmarks" type="Bool">
+ <default>true</default>
+ </entry>
+ <entry name="Compress" type="Bool">
+ <default>true</default>
+ </entry>
+ <entry name="SyncDirection" key="Sync Direction" type="UInt">
+ <default>1</default>
+ </entry>
+ <entry name="IgnoreBmkChanges" key="Ignore only bookmark changes" type="Bool">
+ <default>false</default>
+ </entry>
+ <entry name="AlwaysShowResolutionDialog" key="Always show resolution dialog" type="Bool">
+ <default>false</default>
+ </entry>
+ <entry name="BookmarksToPC" key="Bookmarks to PC" type="UInt">
+ <default>0</default>
+ </entry>
+ <entry name="ConvertedDOCfiles" key="Converted PalmDOCs" type="StringList">
+ <default></default>
+ </entry>
+ <entry name="Encoding" type="String">
+ <default>ISO8859-15</default>
+ </entry>
+ </group>
+
+</kcfg>
diff --git a/kpilot/conduits/docconduit/docconduitSettings.kcfgc b/kpilot/conduits/docconduit/docconduitSettings.kcfgc
new file mode 100644
index 000000000..2a9a3a0f7
--- /dev/null
+++ b/kpilot/conduits/docconduit/docconduitSettings.kcfgc
@@ -0,0 +1,7 @@
+File=docconduit.kcfg
+ClassName=DOCConduitSettings
+Singleton=true
+ItemAccessors=true
+Mutators=true
+GlobalEnums=true
+SetUserTexts=true
diff --git a/kpilot/conduits/docconduit/kpalmdoc.cpp b/kpilot/conduits/docconduit/kpalmdoc.cpp
new file mode 100644
index 000000000..55956cf48
--- /dev/null
+++ b/kpilot/conduits/docconduit/kpalmdoc.cpp
@@ -0,0 +1,58 @@
+/* converter.cpp
+**
+** Copyright (C) 2003 by Reinhold Kainhofer
+**
+** This is the main program of the KDE PalmDOC converter.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include "options.h"
+
+#include <kcmdlineargs.h>
+#include <kaboutdata.h>
+#include <kapplication.h>
+
+#include "kpalmdoc_dlg.h"
+
+
+
+int main(int argc, char *argv[])
+{
+
+ KAboutData about("converter", I18N_NOOP("KPalmDOC"), "-0.0.1",
+ "KPalmDOC - KDE Converter for PalmDOC texts.\n\n",
+ KAboutData::License_GPL, "(c) 2003, Reinhold Kainhofer");
+ about.addAuthor("Reinhold Kainhofer", I18N_NOOP("Main Developer"),
+ "reinhold@kainhofer.com", "http://reinhold.kainhofer.com/Linux/");
+ about.addCredit("Adriaan de Groot", I18N_NOOP("Maintainer of KPilot"),
+ "groot@kde.org", "http://www.kpilot.org/");
+
+ KCmdLineArgs::init(argc, argv, &about);
+ KApplication::addCmdLineOptions();
+
+ KApplication app;
+ ConverterDlg *dlg=new ConverterDlg(0L, i18n("PalmDOC Converter"));
+ dlg->show();
+ return app.exec();
+}
+
diff --git a/kpilot/conduits/docconduit/kpalmdoc.desktop b/kpilot/conduits/docconduit/kpalmdoc.desktop
new file mode 100644
index 000000000..df897fb7d
--- /dev/null
+++ b/kpilot/conduits/docconduit/kpalmdoc.desktop
@@ -0,0 +1,65 @@
+# KDE Config File
+[Desktop Entry]
+Name=KPalmDOC
+Name[hi]=के-पॉम-डॉक
+Name[sv]=Kpalm DOC
+Name[ta]=கேகைdoc
+GenericName=PalmDOC Converter
+GenericName[af]=PalmDOC omskakelaar
+GenericName[bg]=Конвертиране на PalmDOC
+GenericName[bs]=PalmDOC konverter
+GenericName[ca]=Convertidor a PalmDOC
+GenericName[cs]=Konvertor PalmDoc
+GenericName[cy]=Trosiadydd PalmDOC
+GenericName[da]=PalmDOC konverterer
+GenericName[de]=PalmDOC-Konvertierung
+GenericName[el]=ΜετατÏοπέας PalmDOC
+GenericName[eo]=PalmDOC-konvertilo
+GenericName[es]=Conversor de PalmDOC
+GenericName[et]=PalmDOC konverter
+GenericName[eu]=PalmDOC bihurtzailea
+GenericName[fa]=مبدل PalmDOC
+GenericName[fi]=PalmDOC-muunnin
+GenericName[fr]=Convertisseur PalmDOC
+GenericName[fy]=PalmDOC-oersetter
+GenericName[ga]=Tiontaire PalmDOC
+GenericName[gl]=Convertidor de PalmDOC
+GenericName[hi]=पॉम-डॉक परिवरà¥à¤¤à¤•
+GenericName[hu]=PalmDOC-konverter
+GenericName[is]=PalmDOC umbreytir
+GenericName[it]=Convertitore PalmDOC
+GenericName[ja]= PalmDOC コンãƒãƒ¼ã‚¿
+GenericName[ka]=კáƒáƒœáƒ•áƒ”რტáƒáƒ áƒ˜ PalmDOC
+GenericName[kk]=PalmDOC аударғышы
+GenericName[km]=កម្មវិធី​បម្លែង PalmDOC
+GenericName[lt]=PalmDOC konverteris
+GenericName[ms]=Penukar PalmDOC
+GenericName[nb]=PalmDOC-konvertering
+GenericName[nds]=PalmDOC-Ãœmwanneln
+GenericName[ne]=PalmDOC रà¥à¤ªà¤¾à¤¨à¥à¤¤à¤°à¤£à¤•à¤°à¥à¤¤à¤¾
+GenericName[nl]=PalmDOC-conversie
+GenericName[nn]=PalmDOC-omformar
+GenericName[pl]=Konwerter formatu PalmDOC
+GenericName[pt]=Conversor de PalmDOC
+GenericName[pt_BR]=Conversor para PalmDOC
+GenericName[ro]=Convertor PalmDOC
+GenericName[ru]=Конвертер PalmDOC
+GenericName[sk]=PalmDOC prevod
+GenericName[sl]=Pretvornik v PalmDOC
+GenericName[sr]=PalmDOC конвертор
+GenericName[sr@Latn]=PalmDOC konvertor
+GenericName[sv]=Konvertering av Palm DOC
+GenericName[ta]=பாமà¯DOC மாறà¯à®±à®¿
+GenericName[tg]=Конвертёри PalmDOC
+GenericName[tr]=PalmDOC Çevirici
+GenericName[uk]=Перетворювач PalmDOC
+GenericName[zh_CN]=PalmDOC 转æ¢å™¨
+GenericName[zh_TW]=PalmDOC 轉æ›å™¨
+Exec=kpalmdoc
+Icon=kpalmdoc
+Type=Application
+DocPath=kpalmdoc/index.html
+Terminal=false
+X-KDE-StartupNotify=true
+X-DCOP-ServiceType=Unique
+Categories=Qt;KDE;Utility;X-KDE-Utilities-File;Office;PDA;
diff --git a/kpilot/conduits/docconduit/kpalmdoc.kcfg b/kpilot/conduits/docconduit/kpalmdoc.kcfg
new file mode 100644
index 000000000..4d3d22119
--- /dev/null
+++ b/kpilot/conduits/docconduit/kpalmdoc.kcfg
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
+ http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
+ <kcfgfile name="converterrc"/>
+ <group name="General">
+ <entry name="TXTFolder" key="TXT folder" type="Path"/>
+ <entry name="PDBFolder" key="PDB folder" type="Path"/>
+ <entry name="SyncFolders" key="Sync folders" type="Bool">
+ <default>false</default>
+ </entry>
+ <entry name="AskOverwrite" key="Ask before overwriting files" type="Bool">
+ <default>true</default>
+ </entry>
+ <entry name="VerboseMessages" key="Verbose messages" type="Bool">
+ <default>true</default>
+ </entry>
+ <entry name="Compress" type="Bool">
+ <default>true</default>
+ </entry>
+ <entry name="ConvertBookmarks" key="Convert bookmarks" type="Bool">
+ <default>true</default>
+ </entry>
+ <entry name="BookmarksInline" key="Bookmarks inline" type="Bool">
+ <default>true</default>
+ </entry>
+ <entry name="BookmarksEndtags" key="Bookmarks endtags" type="Bool">
+ <default>true</default>
+ </entry>
+ <entry name="BookmarksBmk" key="Bookmarks bmk" type="Bool">
+ <default>true</default>
+ </entry>
+ <entry name="BookmarksToPC" key="Bookmarks to PC" type="UInt">
+ <default>0</default>
+ </entry>
+ <entry name="Encoding" type="String">
+ <default>ISO8859-15</default>
+ </entry>
+ </group>
+</kcfg>
diff --git a/kpilot/conduits/docconduit/kpalmdoc.upd b/kpilot/conduits/docconduit/kpalmdoc.upd
new file mode 100644
index 000000000..77d3d1eeb
--- /dev/null
+++ b/kpilot/conduits/docconduit/kpalmdoc.upd
@@ -0,0 +1,6 @@
+Id=kdepim_3.3
+File=converterrc
+Group=<default>,General
+AllKeys
+
+
diff --git a/kpilot/conduits/docconduit/kpalmdocSettings.kcfgc b/kpilot/conduits/docconduit/kpalmdocSettings.kcfgc
new file mode 100644
index 000000000..6da45c5e2
--- /dev/null
+++ b/kpilot/conduits/docconduit/kpalmdocSettings.kcfgc
@@ -0,0 +1,7 @@
+File=kpalmdoc.kcfg
+ClassName=KPalmDocSettings
+Singleton=true
+ItemAccessors=true
+Mutators=true
+GlobalEnums=true
+SetUserTexts=true
diff --git a/kpilot/conduits/docconduit/kpalmdoc_dlg.cc b/kpilot/conduits/docconduit/kpalmdoc_dlg.cc
new file mode 100644
index 000000000..5bdacba8c
--- /dev/null
+++ b/kpilot/conduits/docconduit/kpalmdoc_dlg.cc
@@ -0,0 +1,529 @@
+/* kpalmdoc_dlg.cpp
+**
+** Copyright (C) 2003 by Reinhold Kainhofer
+**
+** This is the main dialog of the KDE PalmDOC converter.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+#include "options.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <iostream>
+
+#include <qtabwidget.h>
+#include <qcheckbox.h>
+#include <qradiobutton.h>
+#include <qbuttongroup.h>
+#include <qlabel.h>
+#include <qcombobox.h>
+
+#include <klocale.h>
+#include <kconfig.h>
+#include <kaboutapplication.h>
+#include <kapplication.h>
+#include <kurlrequester.h>
+#include <kmessagebox.h>
+#include <kcharsets.h>
+
+#include <pilotLocalDatabase.h>
+
+#include "kpalmdoc_dlg.h"
+#include "kpalmdoc_dlgbase.h"
+#include "DOC-converter.h"
+#include "kpalmdocSettings.h"
+
+
+ConverterDlg::ConverterDlg( QWidget *parent, const QString& caption)
+ : KDialogBase( parent, "converterdialog", false, caption, KDialogBase::Close|KDialogBase::Help|KDialogBase::User1,
+ KDialogBase::Close, true, i18n("&About"))
+{
+ QWidget *page = makeHBoxMainWidget();
+ dlg=new ConverterDlgBase(page);
+ QStringList l = KGlobal::charsets()->descriptiveEncodingNames();
+ for ( QStringList::Iterator it = l.begin(); it != l.end(); ++it)
+ {
+ dlg->fEncoding->insertItem(*it);
+ }
+
+ readSettings();
+
+ connect(dlg->fDirectories, SIGNAL(toggled(bool)),
+ this, SLOT(slotDirectories(bool)));
+ connect(dlg->fTextToPDB, SIGNAL(clicked()), this, SLOT(slotToPDB()));
+ connect(dlg->fPDBToText, SIGNAL(clicked()), this, SLOT(slotToText()));
+
+ resize(minimumSize());
+}
+
+ConverterDlg::~ConverterDlg()
+{
+ // no need to delete child widgets, Qt does it all for us
+}
+void ConverterDlg::writeSettings()
+{
+ // General page
+ KPalmDocSettings::setTXTFolder( dlg->fTXTDir->url() );
+ KPalmDocSettings::setPDBFolder( dlg->fPDBDir->url() );
+ KPalmDocSettings::setSyncFolders( dlg->fDirectories->isChecked() );
+ KPalmDocSettings::setAskOverwrite( dlg->fAskOverwrite->isChecked() );
+ KPalmDocSettings::setVerboseMessages( dlg->fVerbose->isChecked() );
+ KPalmDocSettings::setEncoding( dlg->fEncoding->currentText() );
+
+ // PC->Handheld page
+ KPalmDocSettings::setCompress( dlg->fCompress->isChecked() );
+ KPalmDocSettings::setConvertBookmarks( dlg->fConvertBookmarks->isChecked() );
+ KPalmDocSettings::setBookmarksInline( dlg->fBookmarksInline->isChecked() );
+ KPalmDocSettings::setBookmarksEndtags( dlg->fBookmarksEndtags->isChecked() );
+ KPalmDocSettings::setBookmarksBmk( dlg->fBookmarksBmk->isChecked() );
+
+ // Handheld->PC page
+ KPalmDocSettings::setBookmarksToPC( dlg->fPCBookmarks->id(dlg->fPCBookmarks->selected()) );
+
+ KPalmDocSettings::self()->writeConfig();
+}
+
+void ConverterDlg::readSettings()
+{
+ FUNCTIONSETUP;
+
+ KPalmDocSettings::self()->readConfig();
+
+ // General Page:
+ dlg->fTXTDir->setURL(KPalmDocSettings::tXTFolder());
+ dlg->fPDBDir->setURL(KPalmDocSettings::pDBFolder());
+ bool dir=KPalmDocSettings::syncFolders();
+ dlg->fDirectories->setChecked(dir);
+ slotDirectories(dir);
+ dlg->fAskOverwrite->setChecked( KPalmDocSettings::askOverwrite() );
+ dlg->fVerbose->setChecked( KPalmDocSettings::verboseMessages() );
+ QString encoding = KPalmDocSettings::encoding();
+#ifdef DEBUG
+ DEBUGKPILOT << fname << ": Encoding=" << encoding << endl;
+#endif
+ dlg->fEncoding->setCurrentText( KPalmDocSettings::encoding() );
+
+ // PC->Handheld page
+ dlg->fCompress->setChecked(KPalmDocSettings::compress() );
+ dlg->fConvertBookmarks->setChecked(KPalmDocSettings::convertBookmarks());
+ dlg->fBookmarksInline->setChecked(KPalmDocSettings::bookmarksInline());
+ dlg->fBookmarksEndtags->setChecked(KPalmDocSettings::bookmarksEndtags());
+ dlg->fBookmarksBmk->setChecked(KPalmDocSettings::bookmarksBmk());
+
+ // Handheld->PC page
+ dlg->fPCBookmarks->setButton(KPalmDocSettings::bookmarksToPC() );
+}
+
+void ConverterDlg::slotClose()
+{
+ writeSettings();
+ kapp->quit();
+ delete this;
+}
+
+void ConverterDlg::slotToText()
+{
+ FUNCTIONSETUP;
+ // First, get the settings from the controls and initialize
+ // the converter object
+ int bmks=dlg->fPCBookmarks->id(dlg->fPCBookmarks->selected());
+ DOCConverter conv;
+ switch(bmks) {
+ case 0: conv.setBookmarkTypes(DOCConverter::eBmkNone); break;
+ case 1: conv.setBookmarkTypes(DOCConverter::eBmkInline); break;
+ case 2: conv.setBookmarkTypes(DOCConverter::eBmkEndtags); break;
+ case 3: conv.setBookmarkTypes(DOCConverter::eBmkDefaultBmkFile); break;
+ default:
+ break;
+ }
+
+ askOverwrite=dlg->fAskOverwrite->isChecked();
+ verbose=dlg->fVerbose->isChecked();
+
+
+ bool dir=dlg->fDirectories->isChecked();
+ QString txturl=dlg->fTXTDir->url();
+ QString pdburl=dlg->fPDBDir->url();
+
+ QFileInfo txtinfo(txturl);
+ QFileInfo pdbinfo(pdburl);
+
+ if (dir)
+ {
+ if (pdbinfo.isFile())
+ {
+ int res=KMessageBox::questionYesNo(this,
+ i18n("<qt>You selected to sync folders, "
+ "but gave a filename instead (<em>%1</em>)."
+ "<br>Use folder <em>%2</em> instead?</qt>").arg(pdburl)
+ .arg(pdbinfo.dirPath(true)), QString::null, i18n("Use Folder"), KStdGuiItem::cancel());
+ if (res==KMessageBox::Yes)
+ {
+ pdburl=pdbinfo.dirPath(true);
+ pdbinfo.setFile(pdburl);
+ }
+ else return;
+ }
+
+ if (!pdbinfo.isDir())
+ {
+ // no directory, so error message and return
+ KMessageBox::sorry(this,
+ i18n("<qt>The folder <em>%1</em> for "
+ "the handheld database files is not a valid "
+ "folder.</qt>").arg(pdburl));
+ return;
+ }
+
+ if (!pdbinfo.exists())
+ {
+ KMessageBox::sorry(this,
+ i18n("<qt>The folder <em>%1</em> for "
+ "the handheld database files is not a "
+ "valid directory.</qt>").arg(pdburl));
+ return;
+ }
+
+
+ // Now check the to directory:
+ if (txtinfo.isFile())
+ {
+ int res=KMessageBox::questionYesNo(this,
+ i18n("<qt>You selected to sync folders, "
+ "but gave a filename instead (<em>%1</em>)."
+ "<br>Use folder <em>%2</em> instead?</qt>").arg(txturl)
+ .arg(txtinfo.dirPath(true)), QString::null, i18n("Use Folder"), KStdGuiItem::cancel());
+ if (res==KMessageBox::Yes) {
+ txturl=txtinfo.dirPath(true);
+ txtinfo.setFile(txturl);
+ }
+ else return;
+ }
+
+ // Now that we have a directory path, try to create it:
+ if (!txtinfo.isDir()) {
+ txtinfo.dir().mkdir(txturl, true);
+ }
+ if (!txtinfo.isDir()) {
+ KMessageBox::sorry(this,
+ i18n("<qt>The folder <em>%1</em> for "
+ "the text files could not be created.</qt>").arg(txturl));
+ return;
+ }
+
+
+ // Now that we have both directories, create the converter object
+ DEBUGKPILOT<<"Pdbinfo.dir="<<pdbinfo.dir().absPath()<<endl;
+ DEBUGKPILOT<<"txtinfo.dir="<<txtinfo.dir().absPath()<<endl;
+ QStringList pdbfiles(pdbinfo.dir().entryList(CSL1("*.pdb")));
+ QStringList converted_Files;
+
+ DEBUGKPILOT<<"Length of filename list: "<<pdbfiles.size()<<endl;
+ for ( QStringList::Iterator it = pdbfiles.begin(); it != pdbfiles.end(); ++it )
+ {
+ QString txtfile=QFileInfo(*it).baseName(true)+CSL1(".txt");
+ DEBUGKPILOT<<"pdbfile="<<*it<<", pdbdir="<<pdburl<<", txtfile="<<txtfile<<", txtdir="<<txturl<<endl;
+ if (convertPDBtoTXT(pdburl, *it, txturl, txtfile, &conv))
+ {
+ converted_Files.append(*it);
+ }
+ }
+ if (converted_Files.size()>0) {
+ KMessageBox::informationList(this, i18n("The following texts were "
+ "successfully converted:"), converted_Files, i18n("Conversion Successful"));
+ }
+ else
+ {
+ KMessageBox::sorry(this, i18n("No text files were converted correctly"));
+ }
+
+
+ } else { // no dir
+
+
+ // Check the from file
+ if (!pdbinfo.isFile() || !pdbinfo.exists())
+ {
+ KMessageBox::sorry(this, i18n("<qt>The file <em>%1</em> does not "
+ "exist.</qt>").arg(pdburl));
+ return;
+ }
+
+ // Now check the to file
+/* // I can't check if a given filename is a valid filename
+ if (!txtinfo.isFile())
+ {
+ KMessageBox::sorry(this, i18n("<qt>The filename <em>%1</em> for the "
+ "text is not a valid filename.</qt>").arg(txturl));
+ return;
+ }*/
+ if (convertPDBtoTXT(pdbinfo.dirPath(true), pdbinfo.fileName(),
+ txtinfo.dirPath(true), txtinfo.fileName(), &conv) )
+ {
+ KMessageBox::information(this, i18n("Conversion of file %1 successful.").arg(pdburl));
+ }
+
+ }
+
+}
+
+void ConverterDlg::slotToPDB()
+{
+ FUNCTIONSETUP;
+ // First, get the settings from the controls and initialize
+ // the converter object
+ bool compress=dlg->fCompress->isChecked();
+ int bmks=0;
+ if (dlg->fConvertBookmarks->isChecked())
+ {
+ if (dlg->fBookmarksInline->isChecked()) bmks|=DOCConverter::eBmkInline;
+ if (dlg->fBookmarksEndtags->isChecked()) bmks|=DOCConverter::eBmkEndtags;
+ if(dlg->fBookmarksBmk->isChecked()) bmks|=DOCConverter::eBmkDefaultBmkFile;
+ }
+ DOCConverter conv;
+ conv.setBookmarkTypes(bmks);
+ conv.setCompress(compress);
+ conv.setSort(DOCConverter::eSortName);
+
+
+ askOverwrite=dlg->fAskOverwrite->isChecked();
+ verbose=dlg->fVerbose->isChecked();
+
+
+ bool dir=dlg->fDirectories->isChecked();
+ QString txturl=dlg->fTXTDir->url();
+ QString pdburl=dlg->fPDBDir->url();
+
+ QFileInfo txtinfo(txturl);
+ QFileInfo pdbinfo(pdburl);
+
+ if (dir)
+ {
+ if (txtinfo.isFile())
+ {
+ int res=KMessageBox::questionYesNo(this,
+ i18n("<qt>You selected to sync folders, "
+ "but gave a filename instead (<em>%1</em>)."
+ "<br>Use folder <em>%2</em> instead?</qt>").arg(txturl)
+ .arg(txtinfo.dirPath(true)), QString::null, i18n("Use Folder"), KStdGuiItem::cancel());
+ if (res==KMessageBox::Yes)
+ {
+ txturl=txtinfo.dirPath(true);
+ txtinfo.setFile(txturl);
+ }
+ else return;
+ }
+
+ if (!txtinfo.isDir() || !txtinfo.exists())
+ {
+ KMessageBox::sorry(this,
+ i18n("<qt>The folder <em>%1</em> for "
+ "the text files is not a valid folder.</qt>").arg(txturl));
+ return;
+ }
+
+
+ // Now check the to directory:
+ if (pdbinfo.isFile())
+ {
+ int res=KMessageBox::questionYesNo(this,
+ i18n("<qt>You selected to sync folders, "
+ "but gave a filename instead (<em>%1</em>)."
+ "<br>Use folder <em>%2</em> instead?</qt>")
+ .arg(pdburl)
+ .arg(pdbinfo.dirPath(true)), QString::null, i18n("Use Folder"), KStdGuiItem::cancel());
+ if (res==KMessageBox::Yes) {
+ pdburl=pdbinfo.dirPath(true);
+ pdbinfo.setFile(pdburl);
+ }
+ else return;
+ }
+
+ // Now that we have a directory path, try to create it:
+ if (!pdbinfo.isDir()) {
+ pdbinfo.dir().mkdir(pdburl, true);
+ }
+ if (!pdbinfo.isDir()) {
+ KMessageBox::sorry(this, i18n("<qt>The folder <em>%1</em> for "
+ "the PalmDOC files could not be created.</qt>").arg(pdburl));
+ return;
+ }
+
+
+ // Now that we have both directories, create the converter object
+ DEBUGKPILOT<<"Pdbinfo.dir="<<pdbinfo.dir().absPath()<<endl;
+ DEBUGKPILOT<<"txtinfo.dir="<<txtinfo.dir().absPath()<<endl;
+ QStringList txtfiles(txtinfo.dir().entryList(CSL1("*.txt")));
+ QStringList converted_Files;
+
+ DEBUGKPILOT<<"Length of filename list: "<<txtfiles.size()<<endl;
+ for ( QStringList::Iterator it = txtfiles.begin(); it != txtfiles.end(); ++it )
+ {
+ QString pdbfile=QFileInfo(*it).baseName(true)+CSL1(".pdb");
+ DEBUGKPILOT<<"pdbfile="<<pdbfile<<", pdbdir="<<pdburl<<", txtfile="<<*it<<", txtdir="<<txturl<<endl;
+ if (convertTXTtoPDB(txturl, *it, pdburl, pdbfile, &conv))
+ {
+ converted_Files.append(*it);
+ }
+ }
+ if (converted_Files.size()>0) {
+ KMessageBox::informationList(this, i18n("The following texts were "
+ "successfully converted:"), converted_Files, i18n("Conversion Successful"));
+ }
+ else
+ {
+ KMessageBox::sorry(this, i18n("No text files were converted correctly"));
+ }
+
+
+ } else { // no dir
+
+
+ // Check the from file
+ if (!txtinfo.isFile() || !txtinfo.exists())
+ {
+ KMessageBox::sorry(this, i18n("<qt>The file <em>%1</em> does not "
+ "exist.</qt>").arg(txturl));
+ return;
+ }
+
+ if (convertTXTtoPDB(txtinfo.dirPath(true), txtinfo.fileName(),
+ pdbinfo.dirPath(true), pdbinfo.fileName(), &conv) )
+ {
+ KMessageBox::information(this, i18n("Conversion of file %1 successful.").arg(txturl));
+ }
+
+ }
+
+}
+
+
+void ConverterDlg::slotUser1()
+{
+ KAboutApplication ab(KGlobal::instance()->aboutData(), this);
+ ab.show();
+ ab.exec();
+ return;
+}
+
+void ConverterDlg::slotDirectories(bool dir)
+{
+ FUNCTIONSETUP;
+ DEBUGKPILOT<<"Slot Directories: "<<dir<<endl;
+ if (dir)
+ {
+ dlg->fTextLabel->setText(i18n("&Text folder:"));
+ dlg->fPdbLabel->setText(i18n("&PalmDOC folder:"));
+ dlg->fTXTDir->setMode(KFile::LocalOnly | KFile::Directory);
+ dlg->fPDBDir->setMode(KFile::LocalOnly | KFile::Directory);
+ } else {
+ dlg->fTextLabel->setText(i18n("&Text file:"));
+ dlg->fPdbLabel->setText(i18n("&DOC file:"));
+ dlg->fTXTDir->setMode(KFile::LocalOnly | KFile::File);
+ dlg->fPDBDir->setMode(KFile::LocalOnly | KFile::File);
+ }
+}
+
+bool ConverterDlg::convertTXTtoPDB(QString txtdir, QString txtfile,
+ QString pdbdir, QString pdbfile, DOCConverter*conv)
+{
+ FUNCTIONSETUP;
+ bool res=false;
+ QFileInfo dbfileinfo(pdbdir, pdbfile);
+ DEBUGKPILOT<<"Working on file "<<pdbfile<<endl;
+ if (!dbfileinfo.exists() || !askOverwrite ||
+ (KMessageBox::Yes==KMessageBox::questionYesNo(this,
+ i18n("<qt>The database file <em>%1</em> already exists. Overwrite it?</qt>")
+ .arg(dbfileinfo.filePath()), QString::null, i18n("Overwrite"), KStdGuiItem::cancel() ) ))
+ {
+ PilotLocalDatabase*pdbdb=new PilotLocalDatabase(pdbdir, QFileInfo(pdbfile).baseName(), false);
+ if (pdbdb)
+ {
+ if (!pdbdb->isOpen())
+ {
+#ifdef DEBUG
+ DEBUGKPILOT<<pdbfile<<" does not yet exist. Creating it"<<endl;
+#endif
+ if (!pdbdb->createDatabase(get_long("REAd"), get_long("TEXt")) ) {
+ }
+ }
+
+ if (pdbdb->isOpen())
+ {
+ conv->setPDB(pdbdb);
+ conv->setTXTpath(txtdir, txtfile);
+ DEBUGKPILOT<<"Converting "<<txtfile<<" (dir "<<txtdir<<") to "<<dbfileinfo.filePath()<<endl;
+ if (conv->convertTXTtoPDB()) res=true;
+ }
+ delete pdbdb;
+ }
+ if ( !res && verbose )
+ {
+ KMessageBox::sorry(this, i18n("<qt>Error while converting the text %1.</qt>").arg(txtfile));
+ }
+ }
+ else
+ {
+ DEBUGKPILOT<<"Ignoring the file "<<txtfile<<endl;
+ }
+ return res;
+}
+
+bool ConverterDlg::convertPDBtoTXT(QString pdbdir, QString pdbfile,
+ QString txtdir, QString txtfile, DOCConverter*conv)
+{
+ FUNCTIONSETUP;
+ bool res=false;
+ QFileInfo txtfileinfo(txtdir, txtfile);
+ DEBUGKPILOT<<"Working on file "<<txtfile<<endl;
+ if (!txtfileinfo.exists() || !askOverwrite ||
+ (KMessageBox::Yes==KMessageBox::questionYesNo(this,
+ i18n("<qt>The text file <em>%1</em> already exists. Overwrite it?</qt>")
+ .arg(txtfileinfo.filePath()), QString::null, i18n("Overwrite"), KStdGuiItem::cancel() ) ))
+ {
+ PilotLocalDatabase*pdbdb=new PilotLocalDatabase(pdbdir, QFileInfo(pdbfile).baseName(), false);
+ if (pdbdb)
+ {
+ if (pdbdb->isOpen())
+ {
+ conv->setPDB(pdbdb);
+ conv->setTXTpath(txtdir, txtfile);
+ DEBUGKPILOT<<"Converting "<<txtfile<<" (dir "<<txtdir<<") from "<<pdbfile<<" (dir "<<pdbdir<<")"<<endl;
+ if (conv->convertPDBtoTXT()) res=true;
+ }
+ delete pdbdb;
+ }
+ if ( !res && verbose )
+ {
+ KMessageBox::sorry(this, i18n("<qt>Error while converting the text %1.</qt>").arg(pdbfile));
+ }
+ }
+ else
+ {
+ DEBUGKPILOT<<"Ignoring the file "<<pdbfile<<endl;
+ }
+ return res;
+
+}
+
+#include "kpalmdoc_dlg.moc"
diff --git a/kpilot/conduits/docconduit/kpalmdoc_dlg.h b/kpilot/conduits/docconduit/kpalmdoc_dlg.h
new file mode 100644
index 000000000..410b24568
--- /dev/null
+++ b/kpilot/conduits/docconduit/kpalmdoc_dlg.h
@@ -0,0 +1,67 @@
+/* kpalmdoc_dlg.cpp
+**
+** Copyright (C) 2003 by Reinhold Kainhofer
+**
+** This is the main dialog of the KDE PalmDOC converter.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+#ifndef CONVERTERDLG_H
+#define CONVERTERDLG_H
+
+#include <kdialogbase.h>
+class ConverterDlgBase;
+class DOCConverter;
+
+class ConverterDlg : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+ ConverterDlg( QWidget *parent=0, const QString& caption=0);
+ ~ConverterDlg();
+
+protected slots:
+ virtual void slotClose();
+ void slotToText();
+ void slotToPDB();
+ void slotDirectories(bool dir);
+ void slotUser1();
+protected:
+ void writeSettings();
+ void readSettings();
+
+ // These two functions convert one single file to or from a pdb database
+ bool convertTXTtoPDB(QString txtdir, QString txtfile,
+ QString pdbdir, QString pdbfile, DOCConverter*conv);
+ bool convertPDBtoTXT(QString pdbdir, QString pdbfile,
+ QString txtdir, QString txtfile, DOCConverter*conv);
+
+
+ // The actual dialog widget (designer created) holding all controls
+ ConverterDlgBase*dlg;
+ // Settings
+ bool askOverwrite;
+ bool verbose;
+};
+
+#endif // CONVERTERDLG_H
diff --git a/kpilot/conduits/docconduit/kpalmdoc_dlgbase.ui b/kpilot/conduits/docconduit/kpalmdoc_dlgbase.ui
new file mode 100644
index 000000000..8b3e89668
--- /dev/null
+++ b/kpilot/conduits/docconduit/kpalmdoc_dlgbase.ui
@@ -0,0 +1,435 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>ConverterDlgBase</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>ConverterDlgBase</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>492</width>
+ <height>339</height>
+ </rect>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QTabWidget" row="0" column="0">
+ <property name="name">
+ <cstring>tabWidget</cstring>
+ </property>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>General</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>fPdbLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>4</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;PalmDOC file:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>fPDBDir</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>fTextLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>4</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Text file:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>fTXTDir</cstring>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="2" column="1" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>fDirectories</cstring>
+ </property>
+ <property name="text">
+ <string>Convert whole &amp;folders</string>
+ </property>
+ </widget>
+ <widget class="KURLRequester" row="1" column="1" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>fPDBDir</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Folder where copies of the handheld databases are kept. You can install them to any PalmOS handheld, and distribute these copies to other people (but beware of copyright infringement).</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="3" column="1" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>fAskOverwrite</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Ask before overwriting files</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="4" column="1" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>fVerbose</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Verbose messages</string>
+ </property>
+ </widget>
+ <widget class="KPushButton" row="7" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>fTextToPDB</cstring>
+ </property>
+ <property name="text">
+ <string>Convert Text to PalmDOC</string>
+ </property>
+ </widget>
+ <widget class="KPushButton" row="7" column="2">
+ <property name="name">
+ <cstring>fPDBToText</cstring>
+ </property>
+ <property name="text">
+ <string>Convert PalmDOC to Text</string>
+ </property>
+ </widget>
+ <spacer row="6" column="1">
+ <property name="name">
+ <cstring>spacer5</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>16</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="KURLRequester" row="0" column="1" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>fTXTDir</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Enter the name of the folder where the text files reside on the PC. All files with extension .txt will be synced to the handheld.</string>
+ </property>
+ </widget>
+ <widget class="QComboBox" row="5" column="1" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>fEncoding</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="5" column="0">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Encoding:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>fEncoding</cstring>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>PC -&gt; Handheld</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer row="3" column="0">
+ <property name="name">
+ <cstring>spacer6</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>16</height>
+ </size>
+ </property>
+ </spacer>
+ <spacer row="4" column="0">
+ <property name="name">
+ <cstring>spacer7</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>16</height>
+ </size>
+ </property>
+ </spacer>
+ <spacer row="2" column="0">
+ <property name="name">
+ <cstring>spacer8</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>16</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QCheckBox" row="2" column="1">
+ <property name="name">
+ <cstring>fBookmarksInline</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Inline tags in text</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>When a &lt;* bookmarktext *&gt; appears somewhere in the text, a bookmark will be set at this position, and the text between the &lt;* and the *&gt; will be used as bookmark name. The &lt;*...*&gt; will be removed from the text.</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="3" column="1">
+ <property name="name">
+ <cstring>fBookmarksEndtags</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Tags at end of text</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Tags of the form &lt;bookmarkname&gt; at the end of the text will be used to search the text for the pattern between the &lt; and &gt;. Whenever "bookmarkname" appears in the text, a bookmark will be set there. The endtags &lt;...&gt; will then be removed from the end of the text.</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="0" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>fCompress</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Compress</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Check this box, if the text should be compressed on the handheld to save memory. Most doc reader on the handheld support compressed texts.</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>The Palm doc format supports compressing the text to save memory. If you check this box, the text will consume about 50% less memory than in uncompressed state. Almost all DOC readers on the Palm support compressed texts.</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="1" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>fConvertBookmarks</cstring>
+ </property>
+ <property name="text">
+ <string>Convert &amp;bookmarks</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Do you want to convert bookmarks? Most doc readers support bookmarks. You have to provide some information about where the bookmarks should be set and their titles. Check at least one of the bookmark types below.</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="4" column="1">
+ <property name="name">
+ <cstring>fBookmarksBmk</cstring>
+ </property>
+ <property name="text">
+ <string>Regular &amp;expressions in .bmk file</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Use regular expressions in a file textname.bmk (textname.txt is the filename of the text) to search the text for bookmarks.See the documentation for a description of the format of the bmk file.</string>
+ </property>
+ </widget>
+ <spacer row="5" column="1">
+ <property name="name">
+ <cstring>spacer9</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>21</width>
+ <height>200</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Handheld -&gt; PC</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer row="2" column="0">
+ <property name="name">
+ <cstring>spacer10</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>21</width>
+ <height>190</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QButtonGroup" row="0" column="0">
+ <property name="name">
+ <cstring>fPCBookmarks</cstring>
+ </property>
+ <property name="title">
+ <string>Convert Bookmarks</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QRadioButton" row="1" column="0">
+ <property name="name">
+ <cstring>radioButton9</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Convert as &amp;inline tags</string>
+ </property>
+ <property name="buttonGroupId">
+ <number>1</number>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="0" column="0">
+ <property name="name">
+ <cstring>radioButton8</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Do &amp;not convert bookmarks</string>
+ </property>
+ <property name="buttonGroupId">
+ <number>0</number>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="2" column="0">
+ <property name="name">
+ <cstring>radioButton10</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Convert as &amp;end tags</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="3" column="0">
+ <property name="name">
+ <cstring>radioButton11</cstring>
+ </property>
+ <property name="text">
+ <string>Convert into .bmk &amp;file</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </grid>
+ </widget>
+ </widget>
+ </grid>
+</widget>
+<customwidgets>
+</customwidgets>
+<connections>
+ <connection>
+ <sender>fConvertBookmarks</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>fBookmarksInline</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>fConvertBookmarks</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>fBookmarksEndtags</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>fConvertBookmarks</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>fBookmarksBmk</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+</connections>
+<layoutdefaults spacing="6" margin="11"/>
+<includes>
+ <include location="global" impldecl="in implementation">kurlrequester.h</include>
+ <include location="global" impldecl="in implementation">klineedit.h</include>
+ <include location="global" impldecl="in implementation">kpushbutton.h</include>
+</includes>
+</UI>
diff --git a/kpilot/conduits/docconduit/makedoc9.cc b/kpilot/conduits/docconduit/makedoc9.cc
new file mode 100644
index 000000000..1f1c56ff1
--- /dev/null
+++ b/kpilot/conduits/docconduit/makedoc9.cc
@@ -0,0 +1,405 @@
+// based on: MakeDoc, version 2
+// I only took the tBuf class from there and adapted it.
+//
+// Compresses text files into a format that is ready to export to a Pilot
+// and work with Rick Bram's PilotDOC reader.
+// Copyright (C) Reinhold Kainhofer, 2002
+// Copyrigth (C) Pat Beirne, 2000
+//
+// Original file (makedoc9.cpp) copyright by:
+// Copyright (C) Pat Beirne, 2000.
+// Distributable under the GNU General Public License Version 2 or later.
+//
+// ver 0.6 enforce 31 char limit on database names
+// ver 0.7 change header and record0 to structs
+// ver 2.0 added category control on the command line
+// changed extensions from .prc to .pdb
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <iostream>
+
+
+#include "makedoc9.h"
+
+
+
+//
+// Issue()
+//
+// action: handle the details of writing a single
+// character to the compressed stream
+//
+unsigned
+ tBuf::Issue(byte src, int &bSpace)
+{
+ unsigned int iDest = len;
+ byte *dest = buf;
+
+ // TODO: which of the if parts should really be included???
+#if 0
+ // modified version of issue
+ // just issue the char
+ if (src >= 0x80 || src <= 8)
+ dest[iDest++] = 1;
+ dest[iDest++] = src;
+
+#else
+ // if there is an outstanding space char, see if
+ // we can squeeze it in with an ASCII char
+ if (bSpace)
+ {
+ if (src >= 0x40 && src <= 0x7F)
+ dest[iDest++] = src ^ 0x80;
+ else
+ {
+ // couldn't squeeze it in, so issue the space char by itself
+ // most chars go out simple, except the range 1...8,0x80...0xFF
+ dest[iDest++] = ' ';
+ if (src < 0x80 && (src == 0 || src > 8))
+ dest[iDest++] = src;
+ else
+ dest[iDest++] = 1, dest[iDest++] = src;
+ }
+ // knock down the space flag
+ bSpace = 0;
+ }
+ else
+ {
+ // check for a space char
+ if (src == ' ')
+ bSpace = 1;
+ else
+ {
+ if (src < 0x80 && (src == 0 || src > 8))
+ dest[iDest++] = src;
+ else
+ dest[iDest++] = 1, dest[iDest++] = src;
+
+ }
+ }
+#endif
+ len = iDest;
+ return iDest;
+}
+
+//
+// Compress
+//
+// params: none
+//
+// action: takes the given buffer,
+// and compresses
+// the original data down into a second buffer
+//
+// comment: This version make heavy use of walking pointers.
+//
+unsigned tBuf::Compress()
+{
+ if (!buf)
+ return 0;
+ if (isCompressed) {
+// cout<<"Buffer is already compressed!"<<endl;
+ return len;
+// } else {
+// cout<<" Compressing buffer!!!"<<endl;
+ }
+
+ unsigned int i;
+
+ // run through the input buffer
+ byte *pBuffer; // points to the input buffer
+ byte *pHit; // points to a walking test hit; works upwards on successive matches
+ byte *pPrevHit; // previous value of pHit; also, start of next test
+ byte *pTestHead; // current test string
+ byte *pTestTail; // current walking pointer; one past the current test buffer
+ byte *pEnd; // 1 past the end of the input buffer
+
+ pHit = pPrevHit = pTestHead = pBuffer = buf;
+ pTestTail = pTestHead + 1;
+ pEnd = buf + len; // should point to a 0!
+
+ // make a dest buffer and reassign the local buffer
+ buf = new byte[6000];
+ len = 0; // used to walk through the output buffer
+
+ // loop, absorbing one more char from the input buffer on each pass
+ for (; pTestHead != pEnd; pTestTail++)
+ {
+ // if we already have 10 char match, don't bother scanning again for the 11th (wasted time)
+ if (pTestTail - pTestHead != (1 << COUNT_BITS) + 3)
+ {
+ // scan in the previous data for a match
+ // terminate the test string (and the matcher string, as well!) in a 0
+ byte tmp = *pTestTail;
+
+ *pTestTail = 0;
+ pHit = (byte *) strstr((const char *) pPrevHit,
+ (const char *) pTestHead);
+ *pTestTail = tmp; // restore the char
+ }
+
+ // on a mismatch or end of buffer, issued codes
+ if (pHit == pTestHead
+ || pTestTail - pTestHead > (1 << COUNT_BITS) + 2
+ || pTestTail == pEnd)
+ {
+ // issue the codes
+ // first, check for short runs
+ if (pTestTail - pTestHead < 4)
+ {
+ if (pTestHead[0] > 0x7F || pTestHead[0] <= 8)
+ buf[len++] = 1;
+ buf[len++] = pTestHead[0];
+ pTestHead++;
+ }
+ // for longer runs, issue a run-code
+ else
+ {
+ unsigned int dist = pTestHead - pPrevHit;
+ unsigned int compound =
+ (dist << COUNT_BITS) + pTestTail - pTestHead - 4;
+
+//if (dist>=(1<<DISP_BITS)) printf("\n!! error dist overflow");
+//if (pTestTail-pTestHead-4>7) printf("\n!! error len overflow");
+
+ buf[len++] = 0x80 + (compound >> 8);
+ buf[len++] = compound & 0xFF;
+//printf("\nissuing code for sequence len %d <%c%c%c>",pTestTail-pTestHead-1,pTestHead[0],pTestHead[1],pTestHead[2]);
+//printf("\n <%x%x>",pOut[-2],pOut[-1]);
+ // and start again
+ pTestHead = pTestTail - 1;
+ }
+ // start the search again
+ pPrevHit = pBuffer;
+ // within range
+ if (pTestHead - pPrevHit > ((1 << DISP_BITS) - 1))
+ pPrevHit = pTestHead - ((1 << DISP_BITS) - 1);
+ }
+ // got a match
+ else
+ {
+ pPrevHit = pHit;
+ }
+ // when we get to the end of the buffer, don't inc past the end
+ // this forces the residue chars out one at a time
+ if (pTestTail == pEnd)
+ pTestTail--;
+ }
+
+
+ // final scan to merge consecutive high chars together
+ // and merge space chars
+ unsigned int k;
+
+ for (i = k = 0; i < len; i++, k++)
+ {
+ buf[k] = buf[i];
+ // skip the run-length codes
+ if (buf[k] >= 0x80 && buf[k] < 0xC0)
+ buf[++k] = buf[++i];
+ // if we hit a high char marker, look ahead for another
+ // and merge multiples together
+ else if (buf[k] == 1)
+ {
+ buf[k + 1] = buf[i + 1];
+ while (i + 2 < len && buf[i + 2] == 1 && buf[k] < 8)
+ {
+ buf[k]++;
+ buf[k + buf[k]] = buf[i + 3];
+ i += 2;
+ }
+ k += buf[k];
+ i++;
+ }
+ else if (buf[k] == ' ' && i < len - 1 && buf[i + 1] <= 0x7F
+ && buf[i + 1] >= 0x40)
+ buf[k] = 0x80 | buf[++i];
+ }
+
+ // delete original buffer
+ delete[]pBuffer;
+ len = k;
+
+ isCompressed = true;
+ return k;
+}
+
+/*
+ Decompress
+
+ params: none
+
+ action: make a new buffer
+ run through the source data
+ check the 4 cases:
+ 0,9...7F represent self
+ 1...8 escape n chars
+ 80...bf reference earlier run
+ c0...ff space+ASCII
+
+*/
+unsigned tBuf::Decompress()
+{
+ if (!buf)
+ return 0;
+ if (!isCompressed) {
+// cout<<"Buffer already uncompressed. Doing nothing"<<endl;
+ return len;
+// } else {
+// cout<<"Decompressing buffer"<<endl;
+ }
+
+ // we "know" that all decompresses fit within 4096, right?
+ byte *pOut = new byte[6000];
+ byte *in_buf = buf;
+ byte *out_buf = pOut;
+
+ unsigned int i, j;
+
+ for (j = i = 0; j < len;)
+ {
+ unsigned int c;
+
+ // take a char from the input buffer
+ c = in_buf[j++];
+
+ // separate the char into zones: 0, 1...8, 9...0x7F, 0x80...0xBF, 0xC0...0xFF
+
+ // codes 1...8 mean copy that many bytes; for accented chars & binary
+ if (c > 0 && c < 9)
+ while (c--)
+ out_buf[i++] = in_buf[j++];
+
+ // codes 0, 9...0x7F represent themselves
+ else if (c < 0x80)
+ out_buf[i++] = c;
+
+ // codes 0xC0...0xFF represent "space + ascii char"
+ else if (c >= 0xC0)
+ out_buf[i++] = ' ', out_buf[i++] = c ^ 0x80;
+
+ // codes 0x80...0xBf represent sequences
+ else
+ {
+ int m, n;
+
+ c <<= 8;
+ c += in_buf[j++];
+ m = (c & 0x3FFF) >> COUNT_BITS;
+ n = c & ((1 << COUNT_BITS) - 1);
+ n += 3;
+ while (n--)
+ {
+ out_buf[i] = out_buf[i - m];
+ i++;
+ }
+ }
+ }
+ out_buf[i++]='\0';
+ out_buf[i++]='\0';
+ delete[]buf;
+ buf = pOut;
+ len = i;
+
+ isCompressed = false;
+ return i;
+}
+
+unsigned tBuf::DuplicateCR()
+{
+ if (!buf)
+ return 0;
+ byte *pBuf = new byte[2 * len];
+
+ unsigned int k, j;
+
+ for (j = k = 0; j < len; j++, k++)
+ {
+ pBuf[k] = buf[j];
+ if (pBuf[k] == 0x0A)
+ pBuf[k++] = 0x0D, pBuf[k] = 0x0A;
+ }
+ delete[]buf;
+ buf = pBuf;
+ len = k;
+ return k;
+}
+
+
+
+// this nasty little beast removes really low ASCII and 0's
+// and handles the CR problem
+//
+// if a cr appears before a lf, then remove the cr
+// if a cr appears in isolation, change to a lf
+unsigned tBuf::RemoveBinary()
+{
+ if (!buf)
+ return 0;
+ byte *in_buf = buf;
+ byte *out_buf = new byte[len];
+
+ unsigned int k, j;
+
+ for (j = k = 0; j < len; j++, k++)
+ {
+ // copy each byte
+ out_buf[k] = in_buf[j];
+
+ // throw away really low ASCII
+ if (( /*out_buf[k]>=0 && */ out_buf[k] < 9))
+ k--;
+
+ // for CR
+ if (out_buf[k] == 0x0D)
+ {
+ // if next is LF, then drop it
+ if (j < len - 1 && in_buf[j + 1] == 0x0A)
+ k--;
+ else // turn it into a LF
+ out_buf[k] = 0x0A;
+ }
+ }
+ delete[]buf;
+ buf = out_buf;
+ len = k;
+ return k;
+}
+
+void tBuf::setText(const byte * text, unsigned txtlen, bool txtcomp)
+{
+ if (buf)
+ delete[]buf;
+ buf = 0L;
+
+ if (txtlen <= 0)
+ txtlen = strlen((const char *) text);
+ len = txtlen;
+ buf = new byte[len];
+
+ memcpy(buf, text, len*sizeof(char));
+// strncpy((char *) buf, (const char *) text, len);
+ isCompressed = txtcomp;
+// cout<<"Setting text, compressed="<<txtcomp<<endl;
+}
diff --git a/kpilot/conduits/docconduit/makedoc9.h b/kpilot/conduits/docconduit/makedoc9.h
new file mode 100644
index 000000000..27e3695d4
--- /dev/null
+++ b/kpilot/conduits/docconduit/makedoc9.h
@@ -0,0 +1,111 @@
+#ifndef MAKEDOC_H
+#define MAKEDOC_H
+// based on: MakeDoc, version 2
+// I only took the tBuf class from there and adapted it.
+//
+// Compresses text files into a format that is ready to export to a Pilot
+// and work with Rick Bram's PilotDOC reader.
+// Copyright (C) Reinhold Kainhofer, 2002
+// Copyrigth (C) Pat Beirne, 2000
+//
+// Original file (makedoc9.cpp) copyright by:
+// Copyright (C) Pat Beirne, 2000.
+// Distributable under the GNU General Public License Version 2 or later.
+//
+// ver 0.6 enforce 31 char limit on database names
+// ver 0.7 change header and record0 to structs
+// ver 2.0 added category control on the command line
+// changed extensions from .prc to .pdb
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+#include <stdio.h>
+
+typedef unsigned char byte;
+typedef unsigned long DWORD;
+typedef unsigned short WORD;
+
+#define DISP_BITS 11
+#define COUNT_BITS 3
+
+
+
+
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+///////////////////// //////////////////////
+///////////////////// tBuf class //////////////////////
+///////////////////// //////////////////////
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+
+
+class tBuf {
+ private:
+// byte hichar[10];
+// int hicharnum;
+// bool space;
+
+ byte * buf;
+ unsigned len;
+ bool isCompressed;
+ public:
+ tBuf() {
+ buf = 0L;
+ len=0;
+ isCompressed=false;
+ };
+
+ ~tBuf()
+ {
+ if (buf)
+ delete[]buf;
+ }
+
+ void Clear() {
+ delete[]buf;
+ buf = 0L;
+ }
+ void setText(const byte * text, unsigned int txtlen =
+ 0, bool txtcomp = false);
+ byte *text() const {
+ return buf;
+ }
+ unsigned Len() const {
+ return len;
+ }
+ void setCompressed(bool compressed = true) {
+ isCompressed = compressed;
+ }
+ bool compressed() const {
+ return isCompressed;
+ }
+ unsigned RemoveBinary();
+ unsigned DuplicateCR();
+
+ unsigned Decompress();
+ unsigned Compress();
+
+ private:
+ unsigned Issue(byte src, int &bSpace);
+ void Dump() const {
+ printf("\nbuffer len=%d", len);
+}};
+
+
+#endif
diff --git a/kpilot/conduits/docconduit/pilotDOCBookmark.cc b/kpilot/conduits/docconduit/pilotDOCBookmark.cc
new file mode 100644
index 000000000..9b93f2af1
--- /dev/null
+++ b/kpilot/conduits/docconduit/pilotDOCBookmark.cc
@@ -0,0 +1,87 @@
+/* KPilot
+**
+** Copyright (C) 2002 by Reinhold Kainhofer
+**
+** This is a C++ class for the DOC bookmark record structure
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include "options.h"
+#include "pilotDOCBookmark.h"
+
+
+
+PilotDOCBookmark::PilotDOCBookmark():PilotRecordBase(), pos(0)
+{
+ FUNCTIONSETUP;
+ memset(&bookmarkName[0], 0, 16);
+}
+
+
+
+/* initialize the entry from another one. If rec==NULL, this constructor does the same as PilotDOCBookmark()
+*/
+PilotDOCBookmark::PilotDOCBookmark(PilotRecord * rec):PilotRecordBase(rec)
+{
+ if (rec)
+ {
+ const pi_buffer_t *b = rec->buffer();
+ unsigned int offset = 0;
+ Pilot::dlp<char *>::read(b,offset,bookmarkName,16);
+ bookmarkName[16]='\0';
+ pos = Pilot::dlp<long>::read(b,offset);
+ }
+}
+
+
+
+PilotDOCBookmark::PilotDOCBookmark(const PilotDOCBookmark & e):PilotRecordBase(e)
+{
+ FUNCTIONSETUP;
+ *this = e;
+}
+
+
+
+PilotDOCBookmark & PilotDOCBookmark::operator =(const PilotDOCBookmark & e)
+{
+ if (this != &e)
+ {
+ strncpy(&bookmarkName[0], &e.bookmarkName[0], 16);
+ bookmarkName[16]='\0';
+ pos = e.pos;
+ }
+ return *this;
+}
+
+
+
+PilotRecord *PilotDOCBookmark::pack() const
+{
+ pi_buffer_t *b = pi_buffer_new( 16 + Pilot::dlp<long>::size );
+ pi_buffer_append(b, bookmarkName, 16);
+ b->data[16] = 0;
+ Pilot::dlp<long>::append(b,pos);
+ PilotRecord* rec = new PilotRecord(b, this);
+ return rec;
+}
diff --git a/kpilot/conduits/docconduit/pilotDOCBookmark.h b/kpilot/conduits/docconduit/pilotDOCBookmark.h
new file mode 100644
index 000000000..fe511fc17
--- /dev/null
+++ b/kpilot/conduits/docconduit/pilotDOCBookmark.h
@@ -0,0 +1,51 @@
+/* pilotDOCBookmark.h -*- C++ -*- KPilot
+**
+** Copyright (C) 2003 by Reinhold Kainhofer
+**
+** See the .cc file for an explanation of what this file is for.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+#ifndef _KPILOT_PILOTDOCBOOKMARK_H
+#define _KPILOT_PILOTDOCBOOKMARK_H
+
+#include <pilotRecord.h>
+class PilotRecord;
+
+
+class PilotDOCBookmark:public PilotRecordBase {
+public:
+ PilotDOCBookmark();
+ PilotDOCBookmark(PilotRecord * rec);
+ PilotDOCBookmark(const PilotDOCBookmark & e);
+ ~PilotDOCBookmark() {};
+ PilotDOCBookmark & operator=(const PilotDOCBookmark & e);
+
+ PilotRecord *pack() const;
+
+public:
+ char bookmarkName[17];
+ long int pos;
+};
+
+
+#endif
diff --git a/kpilot/conduits/docconduit/pilotDOCEntry.cc b/kpilot/conduits/docconduit/pilotDOCEntry.cc
new file mode 100644
index 000000000..75a51cefa
--- /dev/null
+++ b/kpilot/conduits/docconduit/pilotDOCEntry.cc
@@ -0,0 +1,92 @@
+/* KPilot
+**
+** Copyright (C) 2002 by Reinhold Kainhofer
+**
+** This is a C++ class dealing with PalmDOC text records
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include "options.h"
+#include "pilotDOCEntry.h"
+
+
+
+const int PilotDOCEntry::TEXT_SIZE = 4096;
+
+
+PilotDOCEntry::PilotDOCEntry():PilotRecordBase()
+{
+ FUNCTIONSETUP;
+ compress = false;
+}
+
+
+
+/* initialize the entry from another one. If rec==NULL, this constructor does the same as PilotDOCEntry()
+*/
+PilotDOCEntry::PilotDOCEntry(PilotRecord * rec, bool compressed):PilotRecordBase(rec)
+{
+ if (rec) fText.setText((unsigned char *) rec->data(), rec->size(), compressed);
+ compress = compressed;
+}
+
+
+
+PilotDOCEntry::PilotDOCEntry(const PilotDOCEntry & e):PilotRecordBase(e)
+{
+ FUNCTIONSETUP;
+ // See PilotDateEntry::operator = for details
+ fText.setText(e.fText.text(), e.fText.Len(), e.fText.compressed());
+ compress = e.compress;
+}
+
+
+
+PilotDOCEntry & PilotDOCEntry::operator =(const PilotDOCEntry & e)
+{
+ if (this != &e)
+ {
+ fText.setText(e.fText.text(), e.fText.Len(), e.fText.compressed());
+ compress = e.compress;
+ }
+ return *this;
+}
+
+
+
+
+PilotRecord *PilotDOCEntry::pack()
+{
+ int len = compress ? fText.Compress() : fText.Decompress();
+
+ if (len<0)
+ {
+ return 0L;
+ }
+
+ pi_buffer_t *b = pi_buffer_new( len + 4 ); // +4 for safety
+ memcpy( b->data, (const char *) fText.text(), len );
+ b->used = len;
+ PilotRecord* rec = new PilotRecord(b, this);
+ return rec;
+}
diff --git a/kpilot/conduits/docconduit/pilotDOCEntry.h b/kpilot/conduits/docconduit/pilotDOCEntry.h
new file mode 100644
index 000000000..b1b9ba45b
--- /dev/null
+++ b/kpilot/conduits/docconduit/pilotDOCEntry.h
@@ -0,0 +1,73 @@
+/* pilotDOCEntry.h -*- C++ -*- KPilot
+**
+** Copyright (C) 2002 by Reinhold Kainhofer
+**
+** See the .cc file for an explanation of what this file is for.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to the mailinlist kde-pim@kde.org
+*/
+#ifndef _KPILOT_PILOTDOCENTRY_H
+#define _KPILOT_PILOTDOCENTRY_H
+
+#include <pilotRecord.h>
+#include "makedoc9.h"
+
+
+class PilotRecord;
+
+
+class PilotDOCEntry:public PilotRecordBase {
+private:
+ bool compress;
+ tBuf fText;
+public:
+ static const int TEXT_SIZE;
+ PilotDOCEntry();
+ PilotDOCEntry(PilotRecord * rec, bool compressed = false);
+ PilotDOCEntry(const PilotDOCEntry & e);
+ ~PilotDOCEntry() {};
+ PilotDOCEntry & operator=(const PilotDOCEntry & e);
+
+
+ QString getText() {
+ fText.Decompress();
+ return QString::fromLatin1((const char *) fText.text());
+ };
+ void setText(QString newtext, bool compressed = false) {
+ fText.setText((const unsigned char *) newtext.latin1(),
+ newtext.length(), compressed);
+ };
+
+ bool getCompress() const {
+ return compress;
+ }
+ void setCompress(bool compressed) {
+ compress = compressed;
+ };
+
+ PilotRecord *pack(); // Not const because it can change the compression
+};
+
+
+
+#endif
+
diff --git a/kpilot/conduits/docconduit/pilotDOCHead.cc b/kpilot/conduits/docconduit/pilotDOCHead.cc
new file mode 100644
index 000000000..1f07e2867
--- /dev/null
+++ b/kpilot/conduits/docconduit/pilotDOCHead.cc
@@ -0,0 +1,101 @@
+/* KPilot
+**
+** Copyright (C) 2002 by Reinhold Kainhofer
+**
+** This is a C++ class dealing with PalmDOC text records
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+#include "options.h"
+#include "pilotDOCHead.h"
+
+#include "makedoc9.h"
+
+
+
+const int PilotDOCHead::textRecordSize = 4096;
+
+PilotDOCHead::PilotDOCHead():PilotRecordBase(),
+version(0),
+spare(0), storyLen(0), numRecords(0), recordSize(textRecordSize), position(0)
+{
+ FUNCTIONSETUP;
+}
+
+
+
+/* initialize the entry from another one. If rec==NULL, this constructor does the same as PilotDOCHead()
+*/
+PilotDOCHead::PilotDOCHead(PilotRecord * rec):PilotRecordBase(rec)
+{
+ const unsigned char *b = (const unsigned char *) rec->data();
+ unsigned int offset = 0;
+
+ version = Pilot::dlp<short>::read(b,offset);
+ spare = Pilot::dlp<short>::read(b,offset);
+ storyLen = Pilot::dlp<long>::read(b,offset);
+ numRecords = Pilot::dlp<short>::read(b,offset);
+ recordSize = Pilot::dlp<short>::read(b,offset);
+ position = Pilot::dlp<long>::read(b,offset);
+}
+
+
+PilotDOCHead::PilotDOCHead(const PilotDOCHead & e):PilotRecordBase(e)
+{
+ FUNCTIONSETUP;
+ *this = e;
+}
+
+
+
+PilotDOCHead & PilotDOCHead::operator =(const PilotDOCHead & e)
+{
+ if (this != &e)
+ {
+ version = e.version;
+ spare = e.spare;
+ storyLen = e.storyLen;
+ numRecords = e.numRecords;
+ recordSize = e.recordSize;
+ position = e.position;
+ }
+ return *this;
+}
+
+
+
+
+PilotRecord *PilotDOCHead::pack() const
+{
+ pi_buffer_t *b = pi_buffer_new(16);
+
+ Pilot::dlp<short>::append(b,version);
+ Pilot::dlp<short>::append(b,spare);
+ Pilot::dlp<long>::append(b,storyLen);
+ Pilot::dlp<short>::append(b,numRecords);
+ Pilot::dlp<short>::append(b,recordSize);
+ Pilot::dlp<long>::append(b,position);
+
+ PilotRecord *rec = new PilotRecord(b, this);
+ return rec;
+}
+
diff --git a/kpilot/conduits/docconduit/pilotDOCHead.h b/kpilot/conduits/docconduit/pilotDOCHead.h
new file mode 100644
index 000000000..aeb7fb526
--- /dev/null
+++ b/kpilot/conduits/docconduit/pilotDOCHead.h
@@ -0,0 +1,62 @@
+/* pilotDOCHead.h -*- C++ -*- KPilot
+**
+** Copyright (C) 2002 by Reinhold Kainhofer
+**
+** See the .cc file for an explanation of what this file is for.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to the mailinlist kde-pim@kde.org
+*/
+#ifndef _KPILOT_PILOTDOCHEAD_H
+#define _KPILOT_PILOTDOCHEAD_H
+
+#include <pilotRecord.h>
+
+class PilotRecord;
+
+
+class PilotDOCHead:public PilotRecordBase {
+ private:
+ static const int textRecordSize;
+
+ public:
+ int version;
+ int spare;
+ long int storyLen;
+ int numRecords;
+ int recordSize;
+ long int position;
+
+ PilotRecord *pack() const;
+
+ public:
+ PilotDOCHead();
+ PilotDOCHead(PilotRecord * rec);
+ PilotDOCHead(const PilotDOCHead & e);
+ ~PilotDOCHead() { }
+
+ PilotDOCHead & operator=(const PilotDOCHead & e);
+};
+
+
+
+#endif
+
diff --git a/kpilot/conduits/docconduit/tests/testcompress.cpp b/kpilot/conduits/docconduit/tests/testcompress.cpp
new file mode 100644
index 000000000..b8367b2b9
--- /dev/null
+++ b/kpilot/conduits/docconduit/tests/testcompress.cpp
@@ -0,0 +1,59 @@
+/*
+** Copyright (C) 2003 by Reinhold Kainhofer
+**
+** This is just a very simple programm to check the compress/uncompress
+** routines by taking one string, compress and then decompress it and
+** see if it is the original string.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+#include <stdio.h>
+#include <iostream.h>
+
+
+#include "../makedoc9.h"
+
+void main ()
+{
+ tBuf fText;
+ char*text="asdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdf";
+
+ fText.setText((const byte*)text);
+ cout<<"Decompressed text: "<<fText.text()<<" ("<<fText.Len()<<") -- Compressed: "<<fText.compressed()<<endl;
+
+ fText.Compress();
+ cout<<" Compressed text: "<<fText.text()<<" ("<<fText.Len()<<") -- Compressed: "<<fText.compressed()<<endl;
+ fText.Decompress();
+ cout<<"Decompressed text: "<<fText.text()<<" ("<<fText.Len()<<") -- Compressed: "<<fText.compressed()<<endl;
+
+ fText.Compress();
+ cout<<" Compressed text: "<<fText.text()<<" ("<<fText.Len()<<") -- Compressed: "<<fText.compressed()<<endl;
+ fText.Decompress();
+ cout<<"Decompressed text: "<<fText.text()<<" ("<<fText.Len()<<") -- Compressed: "<<fText.compressed()<<endl;
+
+ fText.Compress();
+ cout<<" Compressed text: "<<fText.text()<<" ("<<fText.Len()<<") -- Compressed: "<<fText.compressed()<<endl;
+ fText.Decompress();
+ cout<<"Decompressed text: "<<fText.text()<<" ("<<fText.Len()<<") -- Compressed: "<<fText.compressed()<<endl;
+
+
+}
diff --git a/kpilot/conduits/knotes/CMakeLists.txt b/kpilot/conduits/knotes/CMakeLists.txt
new file mode 100644
index 000000000..568adb427
--- /dev/null
+++ b/kpilot/conduits/knotes/CMakeLists.txt
@@ -0,0 +1,52 @@
+include_directories(
+ ${CMAKE_CURRENT_BINARY_DIR}
+)
+
+set(conduit_knotes_SRCS
+ knotes-factory.cc
+ knotes-setup.cc
+ knotes-action.cc
+)
+
+set(conduit_knotes_UIS
+ setup_base.ui
+)
+
+set(conduit_knotes_KCFGS
+ knotesconduitSettings.kcfgc
+)
+
+#set(conduit_knotes_STUBS
+# KNotesIface.h
+#)
+
+#kde3_add_dcop_skels(conduit_knotes_SRCS ${conduit_knotes_STUBS})
+#kde3_add_dcop_stubs(conduit_knotes_SRCS ${conduit_knotes_STUBS})
+
+kde3_add_kcfg_files(conduit_knotes_SRCS ${conduit_knotes_KCFGS})
+kde3_add_ui_files(conduit_knotes_SRCS ${conduit_knotes_UIS})
+kde3_automoc(${conduit_knotes_SRCS})
+
+add_library(conduit_knotes SHARED ${conduit_knotes_SRCS})
+target_link_libraries(conduit_knotes kcal)
+
+set_target_properties(conduit_knotes PROPERTIES
+ LOCATION ${KDE3_PLUGIN_INSTALL_DIR}
+ INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/lib
+ PREFIX ""
+)
+
+kde3_install_libtool_file(conduit_knotes)
+
+install(
+ TARGETS conduit_knotes
+ LIBRARY DESTINATION ${KDE3_PLUGIN_INSTALL_DIR}
+)
+
+install(
+ FILES knotes-conduit.desktop DESTINATION ${KDE3_SERVICES_DIR}
+)
+
+install(
+ FILES knotesconduit.kcfg DESTINATION ${KDE3_KCFG_DIR}
+)
diff --git a/kpilot/conduits/knotes/Makefile.am b/kpilot/conduits/knotes/Makefile.am
new file mode 100644
index 000000000..db4cff3ec
--- /dev/null
+++ b/kpilot/conduits/knotes/Makefile.am
@@ -0,0 +1,21 @@
+INCLUDES= $(PISOCK_INCLUDE) -I$(top_srcdir) -I$(top_srcdir)/kpilot/lib $(all_includes)
+
+METASOURCES = AUTO
+
+servicedir = $(kde_servicesdir)
+service_DATA = knotes-conduit.desktop
+
+kde_module_LTLIBRARIES = conduit_knotes.la
+
+
+conduit_knotes_la_SOURCES = \
+ knotesconduitSettings.kcfgc \
+ knotes-factory.cc \
+ knotes-setup.cc \
+ knotes-action.cc \
+ setup_base.ui
+
+conduit_knotes_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries)
+conduit_knotes_la_LIBADD = ../../lib/libkpilot.la $(LIB_KDEUI)
+
+kde_kcfg_DATA = knotesconduit.kcfg
diff --git a/kpilot/conduits/knotes/cr32-app-knotesconduit.png b/kpilot/conduits/knotes/cr32-app-knotesconduit.png
new file mode 100644
index 000000000..6bca79009
--- /dev/null
+++ b/kpilot/conduits/knotes/cr32-app-knotesconduit.png
Binary files differ
diff --git a/kpilot/conduits/knotes/knotes-action.cc b/kpilot/conduits/knotes/knotes-action.cc
new file mode 100644
index 000000000..905e5ef39
--- /dev/null
+++ b/kpilot/conduits/knotes/knotes-action.cc
@@ -0,0 +1,872 @@
+/* KPilot
+**
+** Copyright (C) 2001 by Dan Pilone
+** Copyright (C) 2002,2003,2004 by Adriaan de Groot
+**
+** This file defines the SyncAction for the knotes-conduit plugin.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include "options.h"
+
+#include <qmap.h>
+#include <qtimer.h>
+
+#include <kapplication.h>
+
+#include <kurl.h>
+#include <libkcal/calendarlocal.h>
+#include <kstandarddirs.h>
+
+
+#include <kconfig.h>
+//#include <dcopclient.h>
+
+#include <time.h> // required by pilot-link includes
+
+#include <pi-memo.h>
+
+#include "pilotMemo.h"
+#include "pilotSerialDatabase.h"
+
+//#include "KNotesIface_stub.h"
+
+#include "knotes-factory.h"
+
+#include "knotes-action.moc"
+#include "knotesconduitSettings.h"
+
+extern "C"
+{
+
+unsigned long version_conduit_knotes = Pilot::PLUGIN_API;
+
+}
+
+typedef QString KNoteID_t;
+typedef const QString &KNoteID_pt;
+
+class NoteAndMemo
+{
+public:
+ NoteAndMemo() : noteId(),memoId(-1) { } ;
+ NoteAndMemo(KNoteID_pt noteid,int memoid) : noteId(noteid),memoId(memoid) { } ;
+ bool operator ==(const NoteAndMemo &p) const
+ {
+ return (p.memo()==memoId) && (p.note()==noteId);
+ }
+
+ int memo() const { return memoId; } ;
+ KNoteID_t note() const { return noteId; } ;
+ inline bool valid() const { return (memoId>0) && (!noteId.isEmpty()) ; } ;
+ QString toString() const { return CSL1("<%1,%2>").arg(noteId).arg(memoId); } ;
+
+ static NoteAndMemo findNote(const QValueList<NoteAndMemo> &,KNoteID_pt note);
+ static NoteAndMemo findMemo(const QValueList<NoteAndMemo> &,int memo);
+
+protected:
+ KNoteID_t noteId;
+ int memoId;
+} ;
+
+NoteAndMemo NoteAndMemo::findNote(const QValueList<NoteAndMemo> &l ,KNoteID_pt note)
+{
+ FUNCTIONSETUP;
+
+ for (QValueList<NoteAndMemo>::ConstIterator it = l.begin();
+ it != l.end();
+ ++it)
+ {
+ if ((*it).note()==note) return *it;
+ }
+
+ return NoteAndMemo();
+}
+
+NoteAndMemo NoteAndMemo::findMemo(const QValueList<NoteAndMemo> &l , int memo)
+{
+ FUNCTIONSETUP;
+
+ for (QValueList<NoteAndMemo>::ConstIterator it =l.begin();
+ it != l.end();
+ ++it)
+ {
+ if ((*it).memo()==memo) return *it;
+ }
+
+ return NoteAndMemo();
+}
+
+class KNotesAction::KNotesActionPrivate
+{
+public:
+ KNotesActionPrivate() :
+ fNotesResource(0L),
+ fTimer(0L),
+ fDeleteCounter(0),
+ fModifiedNotesCounter(0),
+ fModifiedMemosCounter(0),
+ fAddedNotesCounter(0),
+ fAddedMemosCounter(0),
+ fDeletedNotesCounter(0),
+ fDeletedMemosCounter(0),
+ fDeleteNoteForMemo(false)
+ { } ;
+ ~KNotesActionPrivate()
+ {
+ fNotesResource->save();
+
+ KPILOT_DELETE(fNotesResource);
+ KPILOT_DELETE(fTimer);
+ }
+
+ // The record index we're dealing with. Used by
+ // CopyHHToPC sync only.
+ int fRecordIndex;
+
+ KCal::CalendarLocal *fNotesResource;
+ // This is the collection of notes held by KNotes and
+ KCal::Journal::List fNotes;
+
+ // This iterates through that list; it's in here because
+ // we use slots to process one item at a time and need
+ // to keep track of where we are between slot calls.
+ KCal::Journal::List::ConstIterator fIndex;
+
+ // The DCOP client for this application, and the KNotes stub.
+ // DCOPClient *fDCOP;
+ //KNotesIface_stub *fKNotes;
+
+ // The timer for invoking process() to do some more work.
+ QTimer *fTimer;
+
+ // The database we're working with (MemoDB)
+ // PilotSerialDatabase *fDatabase;
+ // Some counter that needs to be preserved between calls to
+ // process(). Typically used to note how much work is done.
+ int fDeleteCounter; // Count deleted memos as well.
+ unsigned int fModifiedNotesCounter; // Count modified KNotes.
+ unsigned int fModifiedMemosCounter;
+ unsigned int fAddedNotesCounter;
+ unsigned int fAddedMemosCounter;
+ unsigned int fDeletedNotesCounter;
+ unsigned int fDeletedMemosCounter;
+
+ // We need to translate between the ids that KNotes uses and
+ // Pilot id's, so we make a list of pairs.
+ //
+ QValueList<NoteAndMemo> fIdList;
+
+ // Setting to delete a KNote when the corresponding memo
+ // has been deleted.
+ bool fDeleteNoteForMemo;
+};
+
+
+
+KNotesAction::KNotesAction(KPilotLink *o,
+ const char *n, const QStringList &a) :
+ ConduitAction(o,n ? n : "knotes-conduit",a),
+ fP(new KNotesActionPrivate)
+{
+ FUNCTIONSETUP;
+
+/*
+ if (fP) fP->fDCOP = KApplication::kApplication()->dcopClient();
+
+ if (fP && !fP->fDCOP)
+ {
+ WARNINGKPILOT << "Can't get DCOP client." << endl;
+ }
+*/
+}
+
+/* virtual */ KNotesAction::~KNotesAction()
+{
+ FUNCTIONSETUP;
+
+ KPILOT_DELETE(fP);
+}
+
+/* virtual */ bool KNotesAction::exec()
+{
+ FUNCTIONSETUP;
+ DEBUGKPILOT << fname << ": Starting knotes conduit." << endl;
+
+ if (syncMode().isTest())
+ {
+ test();
+ delayDone();
+ return true;
+ }
+
+ QString e;
+ if (!openKNotesResource()) return false;
+
+ // Database names seem to be latin1
+ if (!openDatabases(CSL1("MemoDB")))
+ {
+#ifdef DEBUG
+ DEBUGKPILOT << fname << "Can not open databases." << endl;
+#endif
+ emit logError(i18n("Could not open MemoDB on the handheld."));
+ return false;
+ }
+
+ fP->fTimer = new QTimer(this);
+ fActionStatus = Init;
+
+ // this is not needed. As it is done in the initstate in process();
+ // resetIndexes();
+
+ connect(fP->fTimer,SIGNAL(timeout()),SLOT(process()));
+ fP->fTimer->start(0,false);
+
+ return true;
+}
+
+void KNotesAction::test()
+{
+ if (!openKNotesResource()) return;
+ listNotes();
+}
+
+bool KNotesAction::openKNotesResource()
+{
+ FUNCTIONSETUP;
+
+ KConfig korgcfg( locate( "config", CSL1("korganizerrc") ) );
+ korgcfg.setGroup( "Time & Date" );
+ QString tz(korgcfg.readEntry( "TimeZoneId" ) );
+
+ fP->fNotesResource = new KCal::CalendarLocal(tz);
+ KURL mURL = KGlobal::dirs()->saveLocation( "data", "knotes/" ) + "notes.ics";
+
+ if( fP->fNotesResource->load( mURL.path() ) )
+ {
+ fP->fNotes = fP->fNotesResource->journals();
+ return true;
+ }
+ else
+ {
+ emit logError( i18n("Could not load the resource at: %1").arg(mURL.path()) );
+ return false;
+ }
+}
+
+
+void KNotesAction::resetIndexes()
+{
+ FUNCTIONSETUP;
+
+ fP->fRecordIndex = 0;
+ fP->fIndex = fP->fNotes.begin();
+}
+
+void KNotesAction::listNotes()
+{
+ FUNCTIONSETUP;
+
+ KCal::Journal::List notes = fP->fNotesResource->journals();
+ DEBUGKPILOT << fname << ": the resource contains " << notes.size()
+ << " note(s)." << endl;
+
+ KCal::Journal::List::ConstIterator it;
+ int i = 1;
+ for ( it = notes.begin(); it != notes.end(); ++it )
+ {
+ DEBUGKPILOT << fname << ": note " << i << " has id " << (*it)->uid()
+ << endl;
+ i++;
+ }
+
+ DEBUGKPILOT << fname << ": "
+ << "Sync direction: " << syncMode().name() << endl;
+}
+
+/* slot */ void KNotesAction::process()
+{
+ FUNCTIONSETUP;
+
+ DEBUGKPILOT << fname << ": Now in state " << fActionStatus << endl;
+
+ switch(fActionStatus)
+ {
+ case Init:
+ resetIndexes();
+ getAppInfo();
+ getConfigInfo();
+ switch(syncMode().mode())
+ {
+ case SyncAction::SyncMode::eBackup:
+ case SyncAction::SyncMode::eRestore:
+ // Impossible!
+ fActionStatus = Done;
+ break;
+ case SyncAction::SyncMode::eCopyHHToPC :
+ listNotes(); // Debugging
+ fActionStatus = MemosToKNotes;
+ break;
+ case SyncAction::SyncMode::eHotSync:
+ case SyncAction::SyncMode::eFullSync:
+ case SyncAction::SyncMode::eCopyPCToHH:
+ fActionStatus = ModifiedNotesToPilot;
+ break;
+ }
+ break;
+ case ModifiedNotesToPilot:
+ if (modifyNoteOnPilot())
+ {
+ resetIndexes();
+ fActionStatus = DeleteNotesOnPilot;
+ }
+ break;
+ case DeleteNotesOnPilot:
+ if (deleteNoteOnPilot())
+ {
+ resetIndexes();
+ fActionStatus = NewNotesToPilot;
+ }
+ break;
+ case NewNotesToPilot :
+ if (addNewNoteToPilot())
+ {
+ resetIndexes();
+ fDatabase->resetDBIndex();
+ switch(syncMode().mode())
+ {
+ case SyncAction::SyncMode::eBackup:
+ case SyncAction::SyncMode::eRestore:
+ case SyncAction::SyncMode::eCopyHHToPC :
+ // Impossible!
+ fActionStatus = Done;
+ break;
+ case SyncAction::SyncMode::eHotSync:
+ case SyncAction::SyncMode::eFullSync:
+ fActionStatus = MemosToKNotes;
+ break;
+ case SyncAction::SyncMode::eCopyPCToHH:
+ fActionStatus = Cleanup;
+ break;
+ }
+ }
+ break;
+ case MemosToKNotes :
+ if (syncMemoToKNotes())
+ {
+ fActionStatus=Cleanup;
+ }
+ break;
+ case Cleanup :
+ cleanupMemos();
+ break;
+ default :
+ if (fP->fTimer) fP->fTimer->stop();
+ delayDone();
+ }
+}
+
+
+void KNotesAction::getConfigInfo()
+{
+ FUNCTIONSETUP;
+
+ KNotesConduitSettings::self()->readConfig();
+
+ fP->fDeleteNoteForMemo = KNotesConduitSettings::deleteNoteForMemo();
+
+ QValueList<KNoteID_t> notes;
+ QValueList<int> memos;
+
+ // Make this match the type of KNoteID_t !
+ notes=KNotesConduitSettings::noteIds();
+ memos=KNotesConduitSettings::memoIds();
+
+ if (notes.count() != memos.count())
+ {
+ WARNINGKPILOT
+ << ": Notes and memo id lists don't match ("
+ << notes.count()
+ << ","
+ << memos.count()
+ << ")"
+ << endl;
+ notes.clear();
+ memos.clear();
+ setFirstSync( true );
+ }
+
+ QValueList<KNoteID_t>::ConstIterator iNotes = notes.begin();
+ QValueList<int>::ConstIterator iMemos = memos.begin();
+
+ while((iNotes != notes.end()) && (iMemos != memos.end()))
+ {
+ fP->fIdList.append(NoteAndMemo(*iNotes,*iMemos));
+ ++iNotes;
+ ++iMemos;
+ }
+}
+
+void KNotesAction::getAppInfo()
+{
+ FUNCTIONSETUP;
+
+ resetIndexes();
+}
+
+
+bool KNotesAction::modifyNoteOnPilot()
+{
+ FUNCTIONSETUP;
+ return true;
+ /*
+ if (fP->fIndex == fP->fNotes.end())
+ {
+ return true;
+ }
+ */
+
+ //TODO DCOP_REMOVAL
+ /*
+ if (fP->fKNotes->isModified(CSL1("kpilot"),fP->fIndex.key()))
+ {
+#ifdef DEBUG
+ DEBUGKPILOT << fname
+ << ": The note #"
+ << fP->fIndex.key()
+ << " with name "
+ << fP->fIndex.data()
+ << " is modified in KNotes."
+ << endl;
+#endif
+
+ NoteAndMemo nm = NoteAndMemo::findNote(fP->fIdList,
+ fP->fIndex.key());
+
+ if (nm.valid())
+ {
+ QString text,title,body;
+ title = fP->fIndex.data();
+ body = fP->fKNotes->text(fP->fIndex.key());
+ if (body.startsWith(title))
+ {
+ text = body;
+ }
+ else
+ {
+ text = title + CSL1("\n") + body;
+ }
+
+ PilotMemo *a = new PilotMemo(text);
+ PilotRecord *r = a->pack();
+ r->setID(nm.memo());
+
+ int newid = fDatabase->writeRecord(r);
+ fLocalDatabase->writeRecord(r);
+
+ if (newid != nm.memo())
+ {
+ WARNINGKPILOT
+ << ": Memo id changed during write? "
+ << "From "
+ << nm.memo()
+ << " to "
+ << newid
+ << endl;
+ }
+ }
+ else
+ {
+ WARNINGKPILOT << "Modified note unknown to Pilot" << endl;
+ // Add it anyway, with new PilotID.
+ int newid = addNoteToPilot();
+ fP->fIdList.remove(nm);
+ fP->fIdList.append(NoteAndMemo(fP->fIndex.key(),newid));
+ }
+
+ ++(fP->fModifiedMemosCounter);
+ }
+ */
+
+ //++(fP->fIndex);
+ //return false;
+}
+
+bool KNotesAction::deleteNoteOnPilot()
+{
+ FUNCTIONSETUP;
+
+ /*
+ QValueList<NoteAndMemo>::Iterator i = fP->fIdList.begin();
+ while ( i != fP->fIdList.end() )
+ {
+ // TODO DCOP_REMOVE
+ if (fP->fNotes.contains((*i).note()))
+ {
+#ifdef DEBUG
+ DEBUGKPILOT << fname << ": Note " << (*i).note() << " still exists." << endl;
+#endif
+ }
+ else
+ {
+#ifdef DEBUG
+ DEBUGKPILOT << fname << ": Note " << (*i).note() << " is deleted." << endl;
+#endif
+ fDatabase->deleteRecord((*i).memo());
+ fLocalDatabase->deleteRecord((*i).memo());
+ i = fP->fIdList.remove(i);
+ fP->fDeletedMemosCounter++;
+ continue;
+ }
+ ++i;
+ }
+ */
+ return true;
+}
+
+bool KNotesAction::addNewNoteToPilot()
+{
+ FUNCTIONSETUP;
+
+ if (fP->fIndex == fP->fNotes.end())
+ {
+ return true;
+ }
+
+ KCal::Journal *j = (*fP->fIndex);
+
+ if( j->pilotId() == 0 )
+ {
+ DEBUGKPILOT << fname << ": Adding note with id " << j->uid()
+ << " to pilot." << endl;
+
+ int newid = addNoteToPilot();
+
+ ++(fP->fAddedMemosCounter);
+ }
+ //TODO DCOP_REMOVAL
+ /*
+ if (fP->fKNotes->isNew(CSL1("kpilot"),fP->fIndex.key()))
+ {
+ int newid = addNoteToPilot();
+ fP->fIdList.append(NoteAndMemo(fP->fIndex.key(),newid));
+ ++(fP->fAddedMemosCounter);
+ }
+ */
+
+ ++(fP->fIndex);
+ return false;
+}
+
+bool KNotesAction::syncMemoToKNotes()
+{
+ FUNCTIONSETUP;
+
+ PilotRecord *rec = 0L;
+
+ if ( syncMode() == SyncAction::SyncMode::eCopyHHToPC )
+ {
+#ifdef DEBUG
+ DEBUGKPILOT << fname << ": Read record " << fP->fRecordIndex << endl;
+#endif
+ rec = fDatabase->readRecordByIndex(fP->fRecordIndex);
+ fP->fRecordIndex++;
+ }
+ else
+ {
+ rec = fDatabase->readNextModifiedRec();
+ }
+
+ if (!rec)
+ {
+ return true;
+ }
+
+ PilotMemo *memo = new PilotMemo(rec);
+ NoteAndMemo m = NoteAndMemo::findMemo(fP->fIdList,memo->id());
+
+#ifdef DEBUG
+ DEBUGKPILOT << fname << ": Looking at memo "
+ << memo->id()
+ << " which was found "
+ << m.toString()
+ << endl;
+#endif
+
+ if (memo->isDeleted())
+ {
+#ifdef DEBUG
+ DEBUGKPILOT << fname << ": It's been deleted." << endl;
+#endif
+ if (m.valid())
+ {
+ // We knew about the note already, but it
+ // has changed on the Pilot.
+ //
+ //
+ if (fP->fDeleteNoteForMemo)
+ {
+ //TODO DCOP_REMOVAL
+ //fP->fKNotes->killNote(m.note(),KNotesConduitSettings::suppressKNotesConfirm()
+ //) ;
+ fP->fDeletedNotesCounter++;
+ }
+ }
+ else
+ {
+#ifdef DEBUG
+ DEBUGKPILOT << fname << ": It's new and deleted." << endl;
+#endif
+ }
+
+ fLocalDatabase->deleteRecord(rec->id());
+ }
+ else
+ {
+ if (m.valid())
+ {
+ #ifdef DEBUG
+ DEBUGKPILOT << fname << ": It's just modified." << endl;
+ DEBUGKPILOT << fname << ": <"
+// << fP->fNotes[m.note()]
+ << "> <"
+ << memo->shortTitle()
+ << ">"
+ << endl;
+ #endif
+ // Check if KNotes still knows about this note
+ //TODO DCOP_REMOVAL
+ /*
+ if (!(fP->fKNotes->name(m.note()).isEmpty()))
+ {
+ updateNote(m,memo);
+ }
+ else
+ {
+ uint c = fP->fIdList.remove(m);
+ if (!c)
+ {
+ WARNINGKPILOT
+ << "Tried to remove valid note and failed."
+ << endl;
+ }
+ addMemoToKNotes(memo);
+ }
+ */
+ }
+ else
+ {
+ addMemoToKNotes(memo);
+ }
+ fLocalDatabase->writeRecord(rec);
+ }
+
+ KPILOT_DELETE(memo);
+ KPILOT_DELETE(rec);
+
+ return false;
+}
+
+void KNotesAction::updateNote(const NoteAndMemo &m, const PilotMemo *memo)
+{
+ FUNCTIONSETUP;
+ //TODO DCOP_REMOVAL
+ if (true/*fP->fNotes[m.note()] != memo->shortTitle()*/)
+ {
+ // Name changed. KNotes might complain though.
+ //TODO DCOP_REMOVAL
+ //fP->fKNotes->setName(m.note(), memo->shortTitle());
+ }
+ //TODO DCOP_REMOVAL
+ //fP->fKNotes->setText(m.note(),memo->text());
+ fP->fModifiedNotesCounter++;
+}
+
+void KNotesAction::addMemoToKNotes(const PilotMemo *memo)
+{
+ FUNCTIONSETUP;
+ // This note is new to KNotes
+ //TODO DCOP_REMOVAL
+ //KNoteID_t i = fP->fKNotes->newNote(memo->shortTitle(), memo->text());
+ //fP->fIdList.append(NoteAndMemo(i,memo->id()));
+ //fP->fAddedNotesCounter++;
+
+#ifdef DEBUG
+ //TODO DCOP_REMOVAL
+ //DEBUGKPILOT << fname << ": It's new with knote id " << i << endl;
+#endif
+}
+int KNotesAction::addNoteToPilot()
+{
+ FUNCTIONSETUP;
+
+ KCal::Journal *j = (*fP->fIndex);
+
+#ifdef DEBUG
+ DEBUGKPILOT << fname
+ << ": The note #"
+ << j->uid()
+ << " with name "
+ << j->summary()
+ << " is new to the Pilot."
+ << endl;
+#endif
+
+ QString text = j->summary() + CSL1("\n");
+ text.append( j->description() );
+ //TODO DCOP_REMOVAL
+ //text.append(fP->fKNotes->text(fP->fIndex.key()));
+
+ PilotMemo *a = new PilotMemo(text);
+ PilotRecord *r = a->pack();
+
+ int newid = fDatabase->writeRecord(r);
+ fLocalDatabase->writeRecord(r);
+
+ j->setPilotId( newid );
+
+ delete r;
+ delete a;
+ delete j;
+
+ fP->fAddedMemosCounter++;
+
+ return newid;
+}
+
+
+void KNotesAction::cleanupMemos()
+{
+ FUNCTIONSETUP;
+
+ // Tell KNotes we're up-to-date
+ //TODO DCOP_REMOVAL
+ //fP->fKNotes->sync(CSL1("kpilot"));
+
+#ifdef DEBUG
+ DEBUGKPILOT << fname
+ << ": Writing "
+ << fP->fIdList.count()
+ << " pairs to the config file."
+ << endl;
+ DEBUGKPILOT << fname
+ << ": The config file is read-only: "
+ << KNotesConduitSettings::self()->config()->isReadOnly()
+ << endl;
+#endif
+
+ QValueList<KNoteID_t> notes;
+ QValueList<int> memos;
+
+ for (QValueList<NoteAndMemo>::ConstIterator i =
+ fP->fIdList.begin();
+ i!=fP->fIdList.end();
+ ++i)
+ {
+ notes.append((*i).note());
+ memos.append((*i).memo());
+ }
+
+ KNotesConduitSettings::setNoteIds(notes);
+ KNotesConduitSettings::setMemoIds(memos);
+ KNotesConduitSettings::self()->writeConfig();
+
+ fActionStatus=Done;
+ fDatabase->cleanup();
+ fDatabase->resetSyncFlags();
+ fLocalDatabase->cleanup();
+ fLocalDatabase->resetSyncFlags();
+
+ // Tell the user what happened. If no changes were
+ // made, spoke remains false and we'll tack a
+ // message on to the end saying so, so that
+ // the user always gets at least one message.
+ bool spoke = false;
+ if (fP->fAddedMemosCounter)
+ {
+ addSyncLogEntry(i18n("Added one new memo.",
+ "Added %n new memos.",
+ fP->fAddedMemosCounter));
+ }
+ if (fP->fModifiedMemosCounter)
+ {
+ addSyncLogEntry(i18n("Modified one memo.",
+ "Modified %n memos.",
+ fP->fModifiedMemosCounter));
+ spoke = true;
+ }
+ if (fP->fDeletedMemosCounter)
+ {
+ addSyncLogEntry(i18n("Deleted one memo.",
+ "Deleted %n memos.",fP->fDeletedMemosCounter));
+ spoke = true;
+ }
+ if (fP->fAddedNotesCounter)
+ {
+ addSyncLogEntry(i18n("Added one note to KNotes.",
+ "Added %n notes to KNotes.",fP->fAddedNotesCounter));
+ spoke = true;
+ }
+ if (fP->fModifiedNotesCounter)
+ {
+ addSyncLogEntry(i18n("Modified one note in KNotes.",
+ "Modified %n notes in KNotes.",fP->fModifiedNotesCounter));
+ spoke = true;
+ }
+ if (fP->fDeletedNotesCounter)
+ {
+ addSyncLogEntry(i18n("Deleted one note from KNotes.",
+ "Deleted %n notes from KNotes.",fP->fDeletedNotesCounter));
+ spoke = true;
+ }
+ if (!spoke)
+ {
+ addSyncLogEntry(i18n("No change to KNotes."));
+ }
+}
+
+
+/* virtual */ QString KNotesAction::statusString() const
+{
+ switch(fActionStatus)
+ {
+ case Init : return CSL1("Init");
+ case NewNotesToPilot :
+ return CSL1("NewNotesToPilot key=%1");
+ // TODO DCOP_REMOVAL .arg(fP->fIndex.key());
+ case ModifiedNotesToPilot :
+ return CSL1("ModifiedNotesToPilot key=%1");
+ //TODO DCOP_REMOVAL .arg(fP->fIndex.key());
+ case MemosToKNotes :
+ return CSL1("MemosToKNotes rec=%1")
+ .arg(fP->fRecordIndex);
+ case Cleanup : return CSL1("Cleanup");
+ case Done :
+ return CSL1("Done");
+ default :
+ return CSL1("Unknown (%1)").arg(fActionStatus);
+ }
+}
+
+
+
diff --git a/kpilot/conduits/knotes/knotes-action.h b/kpilot/conduits/knotes/knotes-action.h
new file mode 100644
index 000000000..695e90747
--- /dev/null
+++ b/kpilot/conduits/knotes/knotes-action.h
@@ -0,0 +1,113 @@
+#ifndef _KPILOT_KNOTES_ACTION_H
+#define _KPILOT_KNOTES_ACTION_H
+/* knotes-action.h KPilot
+**
+** Copyright (C) 2001,2003 by Dan Pilone
+**
+** This file defines the SyncAction that the KNotes conduit performs.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include <plugin.h>
+
+
+class NoteAndMemo;
+class PilotMemo;
+
+class KNotesAction : public ConduitAction
+{
+Q_OBJECT
+public:
+ KNotesAction(
+ KPilotLink *o,
+ const char *n = 0L,
+ const QStringList &a = QStringList() );
+ virtual ~KNotesAction();
+
+ enum Status { Init,
+ ModifiedNotesToPilot,
+ DeleteNotesOnPilot,
+ NewNotesToPilot,
+ MemosToKNotes,
+ Cleanup,
+ Done } ;
+ virtual QString statusString() const;
+
+protected:
+ virtual bool exec();
+
+protected:
+ /**
+ * For test mode -- just list the notes KNotes has.
+ */
+ void listNotes();
+
+ /** Run a test on the conduit. */
+ void test();
+
+ /**
+ * Loads the KNotes resource and retrieve the list of notes it
+ * has. @return false if the the resource could not be opened and a new
+ * resource could not be created. Modifies fP to store the notes in.
+ */
+ bool openKNotesResource();
+
+ /**
+ * For actual processing. These are called by process
+ * and it is critical that fP->fIndex is set properly.
+ *
+ * Each returns true when it is completely finished processing,
+ * if it returns a bool. Void functions need only be called once.
+ */
+ void getAppInfo();
+ void getConfigInfo();
+ bool modifyNoteOnPilot();
+ bool deleteNoteOnPilot();
+ bool addNewNoteToPilot();
+ bool syncMemoToKNotes();
+ void cleanupMemos();
+
+ void updateNote(const NoteAndMemo &,const PilotMemo *);
+
+ /**
+ * Add the Memo to KNotes.
+ */
+ void addMemoToKNotes(const PilotMemo *);
+ /**
+ * Add the Note currently being processed to the
+ * pilot as a new memo. Returns the id of the record.
+ */
+ int addNoteToPilot();
+
+
+ void resetIndexes();
+
+protected slots:
+ void process();
+
+private:
+ class KNotesActionPrivate;
+ KNotesActionPrivate *fP;
+} ;
+
+#endif
diff --git a/kpilot/conduits/knotes/knotes-conduit.desktop b/kpilot/conduits/knotes/knotes-conduit.desktop
new file mode 100644
index 000000000..7f405cdb1
--- /dev/null
+++ b/kpilot/conduits/knotes/knotes-conduit.desktop
@@ -0,0 +1,94 @@
+[Desktop Entry]
+Type=Service
+Comment=This conduit syncs the Memo Pad application with KNotes.
+Comment[af]=Hierdie pad synkroniseer die Memo Pad program met KNotes.
+Comment[bg]=Ð¡Ð¸Ð½Ñ…Ñ€Ð¾Ð½Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð½Ð° бележки на KDE Ñ Ð¼Ð¾Ð±Ð¸Ð»Ð½Ð¸ уÑтройÑтва
+Comment[bs]=Ovaj conduit sinhronizuje Memo Pad aplikaciju sa KNotes.
+Comment[ca]=Aquest conducte sincronitza l'aplicació Memo Pad amb Knotes.
+Comment[cs]=Toto propojení synchronizuje vašeho Pilota s poznámkami v KNotes.
+Comment[cy]=Mae'r cwndid yma yn cydamseru y cymhwysiad Memo Pad efo KNodiadau.
+Comment[da]=Denne kanal synkroniserer dit memopad-program med KNotes.
+Comment[de]=Abgleich des Memo Pad mit KNotes
+Comment[el]=Αυτός ο σÏνδεσμος συγχÏονίζει την εφαÏμογή Memo Pad με το KNotes.
+Comment[eo]=Tiu kanalo sinkronigas la MemoPad-aplikaĵon kun KNotoj.
+Comment[es]=Este conducto sincroniza la aplicación de Notas con KNotes.
+Comment[et]=See kanal sünkroniseerib Memo Pad rakenduse ja KNotesi.
+Comment[eu]=Kanal honek Memo Pad aplikazioa KNotes-ekin sinkronizatzen du.
+Comment[fa]=این لوله، کاربرد Memo Pad را با KNotes همگام می‌سازد.
+Comment[fi]=Tämä yhdyskäytävä synkronoi Memo Pad -ohelman KNotesin kanssa.
+Comment[fr]=Ce canal synchronise l'application « Memo Pad » avec KNotes.
+Comment[fy]=Dit conduit syngronisearret de Memo Pad mei KNotes.
+Comment[gl]=Este conducto sincroniza a aplicación Memo Pad con KNotes.
+Comment[hi]=यह कनà¥à¤¡à¥à¤¯à¥‚इट मेमो पेड अनà¥à¤ªà¥à¤°à¤¯à¥‹à¤—ों को के-नोटà¥à¤¸ के साथ सिंक करता है
+Comment[hu]=Ezzel a csatolóval a Memo Pad program és a KNotes között lehet szinkronizálást végezni.
+Comment[is]=Þessi rás samstillir lófatölvuna þína við KNotes.
+Comment[it]=Questo condotto sincronizza l'applicazione Memo Pad con KNotes.
+Comment[ja]=ã“ã®ã‚³ãƒ³ã‚¸ãƒƒãƒˆã¯ãƒ¡ãƒ¢å¸³ã‚¢ãƒ—リケーションを KNotes ã¨åŒæœŸã•ã›ã¾ã™ã€‚
+Comment[ka]=ეს áƒáƒ áƒ®áƒ˜ áƒáƒ®áƒ“ენს Memo Pad პრáƒáƒ’რáƒáƒ›áƒ˜áƒ¡ სინქრáƒáƒœáƒ˜áƒ–áƒáƒªáƒ˜áƒáƒ¡ KNotes-თáƒáƒœ.
+Comment[kk]=Memo Pad қолданбаны KNotes жазбаларымен қадамдаÑтыру арнаÑÑ‹.
+Comment[km]=បំពង់​នáŸáŸ‡â€‹áž¢áž¶áž…​ឲ្យ​កម្មវិធី Memo Pad ធ្វើ​សមកាលកម្ម​ជាមួយ​នឹង KNotes ។
+Comment[lt]=Å is kanalas sinchronizuoja Memo Pad programÄ… su KNotes.
+Comment[mk]=Овој канал ја Ñинхронизира апликацијата Memo Pad Ñо КБелешки.
+Comment[ms]=Saluran ini mensegerakkan aplikasi Memo Pad dengan KNotes.
+Comment[nb]=Denne kanalen synkroniserer notatblokk-programmet med KNotes.
+Comment[nds]=Synkroniseert dat Palm-Programm "Memo Pad" mit KNotes.
+Comment[ne]=यो कनà¥à¤¡à¥à¤¯à¥à¤Ÿà¤²à¥‡ मेमो पà¥à¤¯à¤¾à¤¡ अनà¥à¤ªà¥à¤°à¤¯à¥‹à¤— केडीई टिपà¥à¤ªà¤£à¥€à¤®à¤¾ सिनà¥à¤• गरà¥à¤¦à¤› ।
+Comment[nl]=Dit conduit synchroniseert de Memo Pad met KNotes.
+Comment[nn]=Denne koplinga synkroniserer «Memo Pad»-applikasjonen med KNotes.
+Comment[pl]=Ten Å‚Ä…cznik synchronizuje program Memo Pad palmtopa z KNotes (notatkami).
+Comment[pt]=Esta conduta sincroniza os memorandos com o KNotes.
+Comment[pt_BR]=Este conduíte sincroniza a aplicação Memo Pad com o KNotes.
+Comment[ro]=Această conductă sincronizează aplicaţia Memo Pad cu KNotes.
+Comment[ru]=Канал Ñинхронизации заметок КПК и KDE.
+Comment[sk]=Táto spojka synchronizuje aplikáciu Memo Pad s KNotes
+Comment[sl]=Ta veznik usklajuje program Memo Pad s KNotice.
+Comment[sr]=Овај провод Ñинхронизује Memo Pad програме Ñа KNotes-ом.
+Comment[sr@Latn]=Ovaj provod sinhronizuje Memo Pad programe sa KNotes-om.
+Comment[sv]=Den här kanalen synkroniserar programmet Memo Pad med Knotes.
+Comment[ta]=இநà¯à®¤ காபà¯à®ªà¯à®•à¯ கà¯à®´à®¾à®¯à¯ கà¯à®±à®¿à®ªà¯à®ªà®¾à®£à¯ˆ அடà¯à®Ÿà¯ˆ பயனà¯à®ªà®¾à®Ÿà¯ கேகà¯à®±à®¿à®ªà¯à®ªà¯à®•à®³à¯à®Ÿà®©à¯ ஒதà¯à®¤à®¿à®šà¯ˆà®•à¯à®•à®¿à®±à®¤à¯
+Comment[tg]=Канали ÑинхронизатÑиÑи қайдоти Pilot ва KDE.
+Comment[tr]=Bu kanal KNotes ile el bilgisayarınızı senkronize etmenize olanak sağlar
+Comment[uk]=Цей акведук Ñинхронізує Memo Pad з тижневиком KNotes.
+Comment[zh_CN]=此管é“将会将您的备忘程åºä¸Ž KNotes åŒæ­¥ã€‚
+Comment[zh_TW]=此軟體將 KNote 與 Memo Pad 應用程å¼åŒæ­¥ã€‚
+Name=KNotes / Memos
+Name[be]=K Ðататкі
+Name[bg]=KNotes/Memos
+Name[cs]=KNotes / Poznámky
+Name[cy]=KNodiadau/Memos
+Name[da]=KNotes / Memoer
+Name[el]=KNotes / Υπομνήματα
+Name[eo]=KNotoj
+Name[et]=KNotes / memod
+Name[eu]=KNotes / Oharrak
+Name[fr]=KNotes / Mémos
+Name[fy]=KNotes / memo's
+Name[ga]=KNotes / Meamraim
+Name[hi]=के-नोटà¥à¤¸ / मेमो
+Name[hu]=KNotes / memók
+Name[is]=KNotes / minnisblöð
+Name[it]=KNotes / Memo
+Name[ka]=KNotes / ჩáƒáƒœáƒ˜áƒ¨áƒ•áƒœáƒ”ბი
+Name[kk]=KNotes / Жазбалар
+Name[km]=KNotes / អនុស្សរណៈ
+Name[lt]=KNotes / Memo
+Name[mk]=КБелешки / Меморандуми
+Name[ms]=KNotes / Memo
+Name[nds]=KNotes / Notizen
+Name[ne]=केडीई टिपà¥à¤ªà¤£à¥€ / मेमो
+Name[nl]=KNotes / memo's
+Name[nn]=KNotes / Memoar
+Name[pl]=KNotes / Notatki
+Name[pt]=Notas / Memorandos
+Name[pt_BR]=KNotes / Memorandos
+Name[ru]=KNotes / Заметки
+Name[sk]=Poznámky / Memo
+Name[sl]=KNotice / Opomniki
+Name[sv]=Knotes/Memo Pad
+Name[ta]=கேகà¯à®±à®¿à®ªà¯à®ªà¯à®•à®³à¯/கà¯à®±à®¿à®ªà¯à®ªà®¾à®£à¯ˆà®•à®³à¯
+Name[tg]=KNotes / Қайдот
+Name[tr]=KNotlar / Hatırlatmalar
+Name[zh_CN]=KNotes / 备忘
+Implemented=file
+ServiceTypes=KPilotConduit
+X-KDE-Library=conduit_knotes
diff --git a/kpilot/conduits/knotes/knotes-factory.cc b/kpilot/conduits/knotes/knotes-factory.cc
new file mode 100644
index 000000000..a919e1ed1
--- /dev/null
+++ b/kpilot/conduits/knotes/knotes-factory.cc
@@ -0,0 +1,133 @@
+/* KPilot
+**
+** Copyright (C) 2001,2003 by Dan Pilone
+**
+** This file defines the factory for the knotes-conduit plugin.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include "options.h"
+
+#include <kapplication.h>
+#include <kinstance.h>
+#include <kaboutdata.h>
+
+#include <dcopclient.h>
+
+#include <time.h> // Needed by pilot-link include
+
+#include <pi-memo.h>
+
+#include "knotes-action.h"
+#include "knotes-setup.h"
+
+#include "knotes-factory.moc"
+
+
+extern "C"
+{
+
+void *init_conduit_knotes()
+{
+ return new KNotesConduitFactory;
+}
+
+}
+
+
+/* static */ KAboutData *KNotesConduitFactory::fAbout = 0L;
+
+KNotesConduitFactory::KNotesConduitFactory(QObject *p, const char *n) :
+ KLibFactory(p,n)
+{
+ FUNCTIONSETUP;
+
+ fInstance = new KInstance("knotesconduit");
+ fAbout = new KAboutData("knotesconduit",
+ I18N_NOOP("KNotes Conduit for KPilot"),
+ KPILOT_VERSION,
+ I18N_NOOP("Configures the KNotes Conduit for KPilot"),
+ KAboutData::License_GPL,
+ "(C) 2001, Adriaan de Groot");
+ fAbout->addAuthor("Adriaan de Groot",
+ I18N_NOOP("Primary Author"),
+ "groot@kde.org",
+ "http://www.cs.kun.nl/~adridg/kpilot");
+ fAbout->addCredit("David Bishop",
+ I18N_NOOP("UI"));
+}
+
+KNotesConduitFactory::~KNotesConduitFactory()
+{
+ FUNCTIONSETUP;
+
+ KPILOT_DELETE(fInstance);
+ KPILOT_DELETE(fAbout);
+}
+
+/* virtual */ QObject *KNotesConduitFactory::createObject( QObject *p,
+ const char *n,
+ const char *c,
+ const QStringList &a)
+{
+ FUNCTIONSETUP;
+
+#ifdef DEBUG
+ DEBUGKPILOT << fname
+ << ": Creating object of class "
+ << c
+ << endl;
+#endif
+
+ if (qstrcmp(c,"ConduitConfigBase")==0)
+ {
+ QWidget *w = dynamic_cast<QWidget *>(p);
+ if (w)
+ {
+ return new KNotesConfigBase(w,0L);
+ }
+ else
+ {
+ return 0L;
+ }
+ }
+ else
+ if (qstrcmp(c,"SyncAction")==0)
+ {
+ KPilotLink *d = dynamic_cast<KPilotLink *>(p);
+
+ if (d)
+ {
+ return new KNotesAction(d,n,a);
+ }
+ else
+ {
+ WARNINGKPILOT
+ << "Couldn't cast parent to KPilotDeviceLink"
+ << endl;
+ return 0L;
+ }
+ }
+
+ return 0L;
+}
diff --git a/kpilot/conduits/knotes/knotes-factory.h b/kpilot/conduits/knotes/knotes-factory.h
new file mode 100644
index 000000000..94ad44429
--- /dev/null
+++ b/kpilot/conduits/knotes/knotes-factory.h
@@ -0,0 +1,70 @@
+#ifndef _KPILOT_NULL_FACTORY_H
+#define _KPILOT_NULL_FACTORY_H
+/* null-factory.h KPilot
+**
+** Copyright (C) 2001,2003 by Dan Pilone
+**
+** This file defines the factory for the null-conduit plugin.
+** It also defines the class for the behavior of the setup dialog.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include <klibloader.h>
+
+class KInstance;
+class KAboutData;
+
+class KNotesConduitFactory : public KLibFactory
+{
+Q_OBJECT
+
+public:
+ KNotesConduitFactory(QObject * = 0L,const char * = 0L);
+ virtual ~KNotesConduitFactory();
+
+ static KAboutData *about() { return fAbout; } ;
+
+ // The KNotes instance, unlike previous conduits (alphabetically)
+ // has const char * const members. The extra const prevents people
+ // from assigning to this variable, so you have to work hard to
+ // break its value. We store group and entry keys in here.
+
+protected:
+ virtual QObject* createObject( QObject* parent = 0,
+ const char* name = 0,
+ const char* classname = "QObject",
+ const QStringList &args = QStringList() );
+private:
+ KInstance *fInstance;
+ static KAboutData *fAbout;
+} ;
+
+extern "C"
+{
+
+void *init_libknotesconduit();
+
+}
+
+
+#endif
diff --git a/kpilot/conduits/knotes/knotes-setup.cc b/kpilot/conduits/knotes/knotes-setup.cc
new file mode 100644
index 000000000..da8b31c48
--- /dev/null
+++ b/kpilot/conduits/knotes/knotes-setup.cc
@@ -0,0 +1,83 @@
+/* KPilot
+**
+** Copyright (C) 2001,2003 by Dan Pilone
+**
+** This file defines the setup dialog for the knotes-conduit plugin.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include "options.h"
+
+#include <qtabwidget.h>
+#include <qcheckbox.h>
+#include <qmap.h>
+#include <qtimer.h>
+
+#include <kapplication.h>
+#include <kconfig.h>
+
+#include "setup_base.h"
+
+#include "knotes-factory.h"
+#include "knotes-setup.h"
+#include "knotesconduitSettings.h"
+
+
+KNotesConfigBase::KNotesConfigBase(QWidget *w, const char *n) :
+ ConduitConfigBase(w,n),
+ fConfigWidget(0L)
+{
+ fConfigWidget = new KNotesWidget(w);
+ ConduitConfigBase::addAboutPage(fConfigWidget->tabWidget,KNotesConduitFactory::about());
+ fWidget = fConfigWidget;
+ QObject::connect(fConfigWidget->fDeleteNoteForMemo,SIGNAL(clicked()),
+ this,SLOT(modified()));
+ QObject::connect(fConfigWidget->fSuppressConfirm,SIGNAL(clicked()),
+ this,SLOT(modified()));
+ QObject::connect(fConfigWidget->fDeleteNoteForMemo,SIGNAL(toggled(bool)),
+ fConfigWidget->fSuppressConfirm,SLOT(setEnabled(bool)));
+ fConduitName=i18n("KNotes");
+}
+
+void KNotesConfigBase::commit()
+{
+ KNotesConduitSettings::setDeleteNoteForMemo( fConfigWidget->fDeleteNoteForMemo->isChecked() );
+ KNotesConduitSettings::setSuppressKNotesConfirm(fConfigWidget->fSuppressConfirm->isChecked());
+ KNotesConduitSettings::self()->writeConfig();
+ unmodified();
+}
+
+void KNotesConfigBase::load()
+{
+ KNotesConduitSettings::self()->readConfig();
+ fConfigWidget->fDeleteNoteForMemo->setChecked(KNotesConduitSettings::deleteNoteForMemo() );
+ fConfigWidget->fSuppressConfirm->setChecked(KNotesConduitSettings::suppressKNotesConfirm() );
+ fConfigWidget->fSuppressConfirm->setEnabled(KNotesConduitSettings::deleteNoteForMemo());
+ unmodified();
+}
+
+/* static */ ConduitConfigBase *KNotesConfigBase::create(QWidget *w, const char *n)
+{
+ return new KNotesConfigBase(w,n);
+}
+
diff --git a/kpilot/conduits/knotes/knotes-setup.h b/kpilot/conduits/knotes/knotes-setup.h
new file mode 100644
index 000000000..9e7603df7
--- /dev/null
+++ b/kpilot/conduits/knotes/knotes-setup.h
@@ -0,0 +1,49 @@
+#ifndef _KPILOT_KNOTES_SETUP_H
+#define _KPILOT_KNOTES_SETUP_H
+/* knotes-setup.h KPilot
+**
+** Copyright (C) 2001,2003 by Dan Pilone
+**
+** This file defines the widget and behavior for the config dialog
+** of the KNotes conduit.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include "plugin.h"
+
+class KNotesWidget;
+
+class KNotesConfigBase : public ConduitConfigBase
+{
+public:
+ KNotesConfigBase(QWidget *parent, const char *name);
+
+ virtual void commit();
+ virtual void load();
+
+ static ConduitConfigBase *create(QWidget *p, const char *n);
+private:
+ KNotesWidget *fConfigWidget;
+} ;
+
+#endif
diff --git a/kpilot/conduits/knotes/knotesconduit.kcfg b/kpilot/conduits/knotes/knotesconduit.kcfg
new file mode 100644
index 000000000..41d86d2b4
--- /dev/null
+++ b/kpilot/conduits/knotes/knotesconduit.kcfg
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
+ http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
+ <kcfgfile name="kpilot_notesconduitrc"/>
+ <group name="General">
+ <entry name="DeleteNoteForMemo" type="Bool">
+ <default>false</default>
+ </entry>
+ <entry name="SuppressKNotesConfirm" type="Bool">
+ <label>Suppress the confirmation KNotes normally shows when deleting a note.</label>
+ <default>false</default>
+ </entry>
+
+ <entry name="MemoIds" type="IntList">
+ <label>list of the synced MemoDB records</label>
+ <default></default>
+ </entry>
+ <entry name="NoteIds" type="StringList">
+ <label>list of the corresponding KNotes note IDs</label>
+ <default></default>
+ </entry>
+ </group>
+</kcfg>
diff --git a/kpilot/conduits/knotes/knotesconduitSettings.kcfgc b/kpilot/conduits/knotes/knotesconduitSettings.kcfgc
new file mode 100644
index 000000000..33152ac69
--- /dev/null
+++ b/kpilot/conduits/knotes/knotesconduitSettings.kcfgc
@@ -0,0 +1,7 @@
+File=knotesconduit.kcfg
+ClassName=KNotesConduitSettings
+Singleton=true
+ItemAccessors=true
+Mutators=true
+GlobalEnums=true
+SetUserTexts=true
diff --git a/kpilot/conduits/knotes/setup_base.ui b/kpilot/conduits/knotes/setup_base.ui
new file mode 100644
index 000000000..e6aef8042
--- /dev/null
+++ b/kpilot/conduits/knotes/setup_base.ui
@@ -0,0 +1,88 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>KNotesWidget</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>KNotesWidget</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>436</width>
+ <height>394</height>
+ </rect>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QTabWidget">
+ <property name="name">
+ <cstring>tabWidget</cstring>
+ </property>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>General</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox" row="0" column="0">
+ <property name="name">
+ <cstring>fDeleteNoteForMemo</cstring>
+ </property>
+ <property name="text">
+ <string>Delete KNote when Pilot memo is deleted</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Check this box if you wish to delete notes from KNotes automatically when the corresponding Pilot memo is deleted. Use this option with care, as the notes you want to keep in the handheld and in the desktop are not necessarily the same.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="1" column="0">
+ <property name="name">
+ <cstring>fSuppressConfirm</cstring>
+ </property>
+ <property name="text">
+ <string>Suppress delete-confirmation in KNotes</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Check this box if you wish to delete notes from KNotes, without confirmation, when the corresponding Pilot memo is deleted. Use this option only if you want to keep the same notes in the handheld and in the PC.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <spacer row="2" column="0">
+ <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>101</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+ </widget>
+ </widget>
+ </grid>
+</widget>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/kpilot/conduits/malconduit/CMakeLists.txt b/kpilot/conduits/malconduit/CMakeLists.txt
new file mode 100644
index 000000000..092f340fd
--- /dev/null
+++ b/kpilot/conduits/malconduit/CMakeLists.txt
@@ -0,0 +1,48 @@
+include_directories(
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${MAL_INCLUDE_DIR}
+)
+
+set(conduit_mal_SRCS
+ mal-factory.cc
+ mal-setup.cc
+ mal-conduit.cc
+)
+
+set(conduit_mal_UIS
+ mal-setup_dialog.ui
+)
+
+set(conduit_mal_KCFGS
+ malconduitSettings.kcfgc
+)
+
+kde3_add_kcfg_files(conduit_mal_SRCS ${conduit_mal_KCFGS})
+kde3_add_ui_files(conduit_mal_SRCS ${conduit_mal_UIS})
+kde3_automoc(${conduit_mal_SRCS})
+add_library(conduit_mal SHARED ${conduit_mal_SRCS})
+target_link_libraries(conduit_mal ${MAL_LIBRARY})
+
+set_target_properties(
+ conduit_mal PROPERTIES
+ LOCATION ${KDE3_PLUGIN_INSTALL_DIR}
+ PREFIX ""
+ INSTALL_RPATH "${MAL_LIBRARY}"
+ INSTALL_RPATH_USE_LINK_PATH true
+)
+
+kde3_install_libtool_file(conduit_mal)
+
+install(
+ TARGETS conduit_mal
+ LIBRARY DESTINATION ${KDE3_PLUGIN_INSTALL_DIR}
+)
+
+install(
+ FILES mal_conduit.desktop DESTINATION ${KDE3_SERVICES_DIR}
+)
+
+install(
+ FILES malconduit.kcfg DESTINATION ${KDE3_KCFG_DIR}
+)
+
diff --git a/kpilot/conduits/malconduit/Makefile.am b/kpilot/conduits/malconduit/Makefile.am
new file mode 100644
index 000000000..d8a222431
--- /dev/null
+++ b/kpilot/conduits/malconduit/Makefile.am
@@ -0,0 +1,18 @@
+### Makefile for the avantgo conduit
+###
+### The mal conduit is Copyright (C) 2002 by Reinhold Kainhofer
+
+
+INCLUDES= $(PISOCK_INCLUDE) $(MAL_INCLUDE) -I$(top_srcdir)/kpilot/lib $(all_includes)
+METASOURCES = AUTO
+
+servicedir = $(kde_servicesdir)
+service_DATA = mal_conduit.desktop
+kde_kcfg_DATA = malconduit.kcfg
+
+kde_module_LTLIBRARIES = conduit_mal.la
+
+conduit_mal_la_SOURCES = malconduitSettings.kcfgc mal-setup_dialog.ui mal-factory.cc mal-setup.cc mal-conduit.cc
+conduit_mal_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries)
+conduit_mal_la_LIBADD = ../../lib/libkpilot.la $(MAL_LIB) $(LIB_KDEUI)
+
diff --git a/kpilot/conduits/malconduit/README b/kpilot/conduits/malconduit/README
new file mode 100644
index 000000000..deeeb12ef
--- /dev/null
+++ b/kpilot/conduits/malconduit/README
@@ -0,0 +1,12 @@
+KPilot's malconduit
++++++++++++++++++++
+
+Summary: This conduit syncs the handheld with
+ MAL servers such as AvantGo.
+Author: Reinhold Kainhofer, reinhold@kainhofer.com
+Date: August 15, 2002
+License: GPL, linking to libmal (MPL) is explicitly allowed
+Depends: The conduits needs libmal >=0.20 installed
+ (otherwise it will not be compiled). libmal
+ can be downloaded from
+ http://jasonday.home.att.net/code/libmal/
diff --git a/kpilot/conduits/malconduit/mal-conduit.cc b/kpilot/conduits/malconduit/mal-conduit.cc
new file mode 100644
index 000000000..73a77a141
--- /dev/null
+++ b/kpilot/conduits/malconduit/mal-conduit.cc
@@ -0,0 +1,319 @@
+/*
+** MAL conduit for KPilot
+**
+** Copyright (C) 2002 by Reinhold Kainhofer
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+**
+**
+** Specific permission is granted for this code to be linked to libmal
+** (this is necessary because the libmal license is not GPL-compatible).
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+
+
+
+#include "options.h"
+
+#include <qregexp.h>
+#include <kconfig.h>
+#include <kdebug.h>
+
+#include "mal-factory.h"
+#include "mal-conduit.moc"
+#include <libmal.h>
+#include "malconduitSettings.h"
+
+
+static MALConduit *conduitInstance=0L;
+
+int malconduit_logf(const char *, ...) __attribute__ ((format (printf, 1, 2)));
+
+int malconduit_logf(const char *format, ...)
+{
+ FUNCTIONSETUP;
+ va_list val;
+ int rval;
+ va_start(val, format);
+#define WRITE_MAX_BUF 4096
+ char msg[WRITE_MAX_BUF];
+ msg[0]='\0';
+ rval=vsnprintf(&msg[0], sizeof(msg), format, val);
+ va_end(val);
+ if (rval == -1) {
+ msg[WRITE_MAX_BUF-1] = '\0';
+ rval=WRITE_MAX_BUF-1;
+ }
+ if (conduitInstance)
+ {
+ conduitInstance->printLogMessage(msg);
+ }
+ else
+ {
+ // write out to stderr
+ WARNINGKPILOT<< msg << endl;
+ }
+ return rval;
+}
+
+#ifndef LIBMAL20
+int32 cbTask (void * /*out*/,
+ int32 * /*returnErrorCode*/,
+ char *currentTask,
+ AGBool /*bufferable*/)
+{
+ if (currentTask) {
+ malconduit_logf ("%s\n", currentTask);
+ }
+
+ return AGCLIENT_CONTINUE;
+}
+
+static int32 cbItem (void */*out*/,
+ int32 * /*returnErrorCode*/,
+ int32 /*currentItemNumber*/,
+ int32 /*totalItemCount*/,
+ char * /*currentItem*/)
+{
+// The log widget only supports writing out whole lines. You just can't add a single character
+// to the last line. Thus I completely remove the pseudo-percentbar.
+/* malconduit_logf (".");
+
+ if (currentItemNumber == totalItemCount) {
+ malconduit_logf ("\n");
+ }
+*/
+ return AGCLIENT_CONTINUE;
+}
+#endif
+
+
+MALConduit::MALConduit(KPilotLink * o,
+ const char *n,
+ const QStringList & a) :
+ ConduitAction(o, n, a)
+{
+ FUNCTIONSETUP;
+#ifdef LIBMAL20
+ register_printStatusHook(malconduit_logf);
+ register_printErrorHook(malconduit_logf);
+#endif
+ conduitInstance=this;
+ fConduitName=i18n("MAL");
+}
+
+
+
+MALConduit::~MALConduit()
+{
+ FUNCTIONSETUP;
+}
+
+
+
+void MALConduit::readConfig()
+{
+ FUNCTIONSETUP;
+ MALConduitSettings::self()->readConfig();
+#ifdef DEBUG
+ DEBUGKPILOT<<"Last sync was "<<MALConduitSettings::lastMALSync().toString()<<endl;
+#endif
+}
+
+
+
+void MALConduit::saveConfig()
+{
+ FUNCTIONSETUP;
+ MALConduitSettings::setLastMALSync( QDateTime::currentDateTime() );
+ MALConduitSettings::self()->writeConfig();
+}
+
+
+
+bool MALConduit::skip()
+{
+ QDateTime now=QDateTime::currentDateTime();
+ QDateTime lastSync=MALConduitSettings::lastMALSync();
+
+ if (!lastSync.isValid() || !now.isValid()) return false;
+
+ switch ( MALConduitSettings::syncFrequency() )
+ {
+ case MALConduitSettings::eEveryHour:
+ if ( (lastSync.secsTo(now)<=3600) && (lastSync.time().hour()==now.time().hour()) ) return true;
+ else return false;
+ case MALConduitSettings::eEveryDay:
+ if ( lastSync.date() == now.date() ) return true;
+ else return false;
+ case MALConduitSettings::eEveryWeek:
+ if ( (lastSync.daysTo(now)<=7) && ( lastSync.date().dayOfWeek()<=now.date().dayOfWeek()) ) return true;
+ else return false;
+ case MALConduitSettings::eEveryMonth:
+ if ( (lastSync.daysTo(now)<=31) && (lastSync.date().month()==now.date().month()) ) return true;
+ else return false;
+ case MALConduitSettings::eEverySync:
+ default:
+ return false;
+ }
+ return false;
+}
+
+
+
+/* virtual */ bool MALConduit::exec()
+{
+ FUNCTIONSETUP;
+
+ readConfig();
+
+ // TODO: set the log/error message hooks of libmal here!!!
+
+ if (skip())
+ {
+ emit logMessage(i18n("Skipping MAL sync, because last synchronization was not long enough ago."));
+ emit syncDone(this);
+ return true;
+ }
+
+ // Now initiate the sync.
+ PalmSyncInfo* pInfo=syncInfoNew();
+ if (!pInfo) {
+ WARNINGKPILOT << "Could not allocate SyncInfo!" << endl;
+ emit logError(i18n("MAL synchronization failed (no SyncInfo)."));
+ return false;
+ }
+
+ QString proxyServer( MALConduitSettings::proxyServer() );
+ int proxyPort( MALConduitSettings::proxyPort() );
+ QString syncMessage;
+ bool canContinue = true;
+ // Set all proxy settings
+ switch (MALConduitSettings::proxyType())
+ {
+ case MALConduitSettings::eProxyHTTP:
+ if (proxyServer.isEmpty())
+ {
+ canContinue = false;
+ syncMessage = i18n("No proxy server is set.");
+ break;
+ }
+ syncMessage = i18n("Using proxy server: %1").arg(proxyServer);
+
+#ifdef DEBUG
+ DEBUGKPILOT<<" Using HTTP proxy server \""<<proxyServer<<
+ "\", Port "<<proxyPort<<", User "<<MALConduitSettings::proxyUser()<<
+ ", Password "<<( (MALConduitSettings::proxyPassword().isEmpty())?QString("not "):QString())<<"set"
+ <<endl;
+#endif
+#ifdef LIBMAL20
+ setHttpProxy(const_cast<char *>(proxyServer.latin1()));
+ if (proxyPort>0 && proxyPort<65536) setHttpProxyPort( proxyPort );
+ else setHttpProxyPort(80);
+#else
+ pInfo->httpProxy = new char[ proxyServer.length() + 1 ];
+ strlcpy( pInfo->httpProxy, proxyServer.latin1(), proxyServer.length() + 1);
+ if (proxyPort>0 && proxyPort<65536) pInfo->httpProxyPort = proxyPort;
+ else pInfo->httpProxyPort = 80;
+#endif
+
+ if (!MALConduitSettings::proxyUser().isEmpty())
+ {
+#ifdef LIBMAL20
+ setProxyUsername( const_cast<char *>(MALConduitSettings::proxyUser().latin1()) );
+ if (!MALConduitSettings::proxyPassword().isEmpty()) setProxyPassword( const_cast<char *>(MALConduitSettings::proxyPassword().latin1()) );
+#else
+ pInfo->proxyUsername = new char[ MALConduitSettings::proxyUser().length() + 1 ];
+ strlcpy( pInfo->proxyUsername, MALConduitSettings::proxyUser().latin1(), MALConduitSettings::proxyUser().length() + 1);
+ if (!MALConduitSettings::proxyPassword().isEmpty()) {
+// pInfo->proxyPassword = MALConduitSettings::proxyPassword().latin1();
+ pInfo->proxyPassword = new char[ MALConduitSettings::proxyPassword().length() + 1 ];
+ strlcpy( pInfo->proxyPassword, MALConduitSettings::proxyPassword().latin1(), MALConduitSettings::proxyPassword().length() + 1);
+ }
+#endif
+ }
+ break;
+ case MALConduitSettings::eProxySOCKS:
+ if (proxyServer.isEmpty())
+ {
+ canContinue = false;
+ syncMessage = i18n("No SOCKS proxy is set.");
+ break;
+ }
+ syncMessage = i18n("Using SOCKS proxy: %1").arg(proxyServer);
+#ifdef DEBUG
+ DEBUGKPILOT<<" Using SOCKS proxy server \""<<proxyServer<<"\", Port "<<proxyPort<<", User "<<MALConduitSettings::proxyUser()<<", Password "<<( (MALConduitSettings::proxyPassword().isEmpty())?QString("not "):QString() )<<"set"<<endl;
+#endif
+#ifdef LIBMAL20
+ setSocksProxy( const_cast<char *>(proxyServer.latin1()) );
+ if (proxyPort>0 && proxyPort<65536) setSocksProxyPort( proxyPort );
+ else setSocksProxyPort(1080);
+#else
+// pInfo->socksProxy = proxyServer.latin1();
+ pInfo->socksProxy = new char[ proxyServer.length() + 1 ];
+ strlcpy( pInfo->socksProxy, proxyServer.latin1(), proxyServer.length() + 1);
+ if (proxyPort>0 && proxyPort<65536) pInfo->socksProxyPort = proxyPort;
+ else pInfo->socksProxyPort = 1080;
+#endif
+ break;
+ default:
+ break;
+ }
+
+ logMessage(syncMessage);
+
+ if (!canContinue)
+ {
+ return false;
+ }
+
+#ifdef LIBMAL20
+ malsync( pilotSocket(), pInfo);
+#else
+ pInfo->sd = pilotSocket();
+ pInfo->taskFunc = cbTask;
+ pInfo->itemFunc = cbItem;
+ malsync( pInfo );
+ delete[] pInfo->httpProxy;
+ delete[] pInfo->proxyUsername;
+ delete[] pInfo->proxyPassword;
+ delete[] pInfo->socksProxy;
+ syncInfoFree(pInfo);
+#endif
+
+ saveConfig();
+ return delayDone();
+}
+
+void MALConduit::printLogMessage(QString msg)
+{
+ FUNCTIONSETUP;
+ // Remove the pseudo-progressbar:
+ QString newmsg(msg);
+ newmsg.replace( QRegExp("^\\s*\\.*\\s*"), "");
+ newmsg.replace( QRegExp("\\s*\\.*\\s*$"), "");
+ if (newmsg.length()>0)
+ {
+ emit logMessage(newmsg);
+ }
+}
+
diff --git a/kpilot/conduits/malconduit/mal-conduit.h b/kpilot/conduits/malconduit/mal-conduit.h
new file mode 100644
index 000000000..83f72ace1
--- /dev/null
+++ b/kpilot/conduits/malconduit/mal-conduit.h
@@ -0,0 +1,66 @@
+#ifndef _MAL_CONDUIT_H
+#define _MAL_CONDUIT_H
+/* mal-conduit.h KPilot
+**
+** Copyright (C) 2002 by Reinhold Kainhofer
+**
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+**
+**
+** Specific permission is granted for this code to be linked to libmal
+** (this is necessary because the libmal license is not GPL-compatible).
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+
+
+#include <plugin.h>
+
+class MALConduit : public ConduitAction
+{
+Q_OBJECT
+public:
+ MALConduit(
+ KPilotLink *o,
+ const char *n = 0L,
+ const QStringList &a = QStringList() );
+ virtual ~MALConduit();
+ void printLogMessage(QString msg);
+ virtual bool exec();
+
+protected:
+ /**
+ * Read in the config from the KPilot config files and fill the member variables accordingly
+ */
+ void readConfig();
+ /**
+ * Store the sync time in the KPilot configuration
+ */
+ void saveConfig();
+ /**
+ * Check if the last sync was not so long ago that according to MALConduitSettings::syncFrequency() we can skip the sync this time
+ */
+ bool skip();
+} ;
+
+
+#endif
diff --git a/kpilot/conduits/malconduit/mal-factory.cc b/kpilot/conduits/malconduit/mal-factory.cc
new file mode 100644
index 000000000..f9a8bcafb
--- /dev/null
+++ b/kpilot/conduits/malconduit/mal-factory.cc
@@ -0,0 +1,143 @@
+/* Time-factory.cc KPilot
+**
+** Copyright (C) 2002 by Reinhold Kainhofer
+**
+** This file defines the factory for the MAL-conduit plugin.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+**
+**
+** Specific permission is granted for this code to be linked to libmal
+** (this is necessary because the libmal license is not GPL-compatible).
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include "options.h"
+
+#include <kapplication.h>
+#include <kinstance.h>
+#include <kaboutdata.h>
+
+#include <time.h> // Needed by pilot-link include
+#include "mal-conduit.h"
+#include "mal-setup.h"
+
+#include "mal-factory.moc"
+
+
+extern "C"
+{
+
+void *init_conduit_mal()
+{
+ return new MALConduitFactory;
+}
+
+unsigned long version_conduit_mal = Pilot::PLUGIN_API;
+
+}
+
+
+// A number of static variables
+//
+KAboutData *MALConduitFactory::fAbout = 0L;
+
+MALConduitFactory::MALConduitFactory(QObject *p, const char *n) :
+ KLibFactory(p,n)
+{
+ FUNCTIONSETUP;
+
+ fInstance = new KInstance("MALconduit");
+ fAbout = new KAboutData("MALconduit",
+ I18N_NOOP("MAL Synchronization Conduit for KPilot"),
+ KPILOT_VERSION,
+ I18N_NOOP("Synchronizes the content from MAL Servers like AvantGo to the Handheld"),
+ KAboutData::License_GPL,
+ "(C) 2002, Reinhold Kainhofer");
+ fAbout->addAuthor("Reinhold Kainhofer",
+ I18N_NOOP("Primary Author"), "reinhold@kainhofer.com", "http://reinhold.kainhofer.com/");
+ fAbout->addCredit("Jason Day",
+ I18N_NOOP("Author of libmal and the JPilot AvantGo conduit"), "jasonday@worldnet.att.net");
+ fAbout->addCredit("Tom Whittaker",
+ I18N_NOOP("Author of syncmal"), "tom@tomw.org", "http://www.tomw.org/");
+ fAbout->addCredit("AvantGo, Inc.",
+ I18N_NOOP("Authors of the malsync library (c) 1997-1999"), "", "http://www.avantgo.com/");
+}
+
+MALConduitFactory::~MALConduitFactory()
+{
+ FUNCTIONSETUP;
+
+ KPILOT_DELETE(fInstance);
+ KPILOT_DELETE(fAbout);
+}
+
+/* virtual */ QObject *MALConduitFactory::createObject( QObject *p,
+ const char *n,
+ const char *c,
+ const QStringList &a)
+{
+ FUNCTIONSETUP;
+
+#ifdef DEBUG
+ DEBUGKPILOT << fname
+ << ": Creating object of class "
+ << c
+ << endl;
+#endif
+
+ if (qstrcmp(c,"ConduitConfigBase")==0)
+ {
+ QWidget *w = dynamic_cast<QWidget *>(p);
+
+ if (w)
+ {
+ return new MALWidgetSetup(w,n);
+ }
+ else
+ {
+ WARNINGKPILOT
+ << "Couldn't cast parent to widget."
+ << endl;
+ return 0L;
+ }
+ }
+
+ if (qstrcmp(c,"SyncAction")==0)
+ {
+ KPilotLink *d = dynamic_cast<KPilotLink *>(p);
+
+ if (d)
+ {
+ return new MALConduit(d,n,a);
+ }
+ else
+ {
+ WARNINGKPILOT
+ << "Couldn't cast parent to KPilotLink"
+ << endl;
+ return 0L;
+ }
+ }
+
+ return 0L;
+}
+
diff --git a/kpilot/conduits/malconduit/mal-factory.h b/kpilot/conduits/malconduit/mal-factory.h
new file mode 100644
index 000000000..82631e1ac
--- /dev/null
+++ b/kpilot/conduits/malconduit/mal-factory.h
@@ -0,0 +1,67 @@
+#ifndef _TIME_FACTORY_H
+#define _TIME_FACTORY_H
+/* MAL-factory.h KPilot
+**
+** Copyright (C) 2002 by Reinhold Kainhofer
+**
+** This file defines the factory for the mal-conduit plugin.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+**
+**
+** Specific permission is granted for this code to be linked to libmal
+** (this is necessary because the libmal license is not GPL-compatible).
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include <klibloader.h>
+
+class KInstance;
+class KAboutData;
+
+class MALConduitFactory : public KLibFactory
+{
+Q_OBJECT
+
+public:
+ MALConduitFactory(QObject * = 0L,const char * = 0L);
+ virtual ~MALConduitFactory();
+
+ static KAboutData *about() { return fAbout; } ;
+
+protected:
+ virtual QObject* createObject( QObject* parent = 0,
+ const char* name = 0,
+ const char* classname = "QObject",
+ const QStringList &args = QStringList() );
+private:
+ KInstance *fInstance;
+ static KAboutData *fAbout;
+} ;
+
+extern "C"
+{
+
+void *init_libtimeconduit();
+
+}
+
+#endif
diff --git a/kpilot/conduits/malconduit/mal-setup.cc b/kpilot/conduits/malconduit/mal-setup.cc
new file mode 100644
index 000000000..d2652b035
--- /dev/null
+++ b/kpilot/conduits/malconduit/mal-setup.cc
@@ -0,0 +1,185 @@
+/* MAL-setup.cc KPilot
+**
+** Copyright (C) 2002 by Reinhold Kainhofer
+**
+** This file defines the setup dialog for the MAL-conduit plugin.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+**
+**
+** Specific permission is granted for this code to be linked to libmal
+** (this is necessary because the libmal license is not GPL-compatible).
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include "options.h"
+
+#include <qtabwidget.h>
+#include <qradiobutton.h>
+#include <qbuttongroup.h>
+#include <qlineedit.h>
+#include <qcheckbox.h>
+
+#include <kcombobox.h>
+#include <knuminput.h>
+#include <kpassdlg.h>
+
+#include <kapplication.h>
+#include <kconfig.h>
+
+
+#include "mal-setup_dialog.h"
+
+#include "mal-factory.h"
+#include "mal-setup.moc"
+#include "malconduitSettings.h"
+
+
+MALWidgetSetup::MALWidgetSetup(QWidget *w, const char *n) :
+ ConduitConfigBase(w,n),
+ fConfigWidget(new MALWidget(w))
+{
+ FUNCTIONSETUP;
+
+ fConduitName=i18n("MAL");
+ ConduitConfigBase::addAboutPage(fConfigWidget->tabWidget,MALConduitFactory::about());
+ fWidget = fConfigWidget;
+
+ fConfigWidget->tabWidget->adjustSize();
+ fConfigWidget->resize(fConfigWidget->tabWidget->size());
+#define CM(a,b) connect(fConfigWidget->a,b,this,SLOT(modified()));
+ CM( syncTime, SIGNAL(clicked(int)) );
+ CM( proxyType, SIGNAL(clicked(int)) );
+
+ CM( proxyServerName, SIGNAL(textChanged(const QString &)) );
+ CM( proxyCustomPortCheck, SIGNAL(clicked()) );
+ CM( proxyCustomPort, SIGNAL(valueChanged(int)) );
+ CM( proxyUserName, SIGNAL(textChanged(const QString &)) );
+ CM( proxyPassword, SIGNAL(textChanged(const QString &)) );
+
+ CM( malServerName, SIGNAL(textChanged(const QString &)) );
+ CM( malCustomPortCheck, SIGNAL(clicked()) );
+ CM( malCustomPort, SIGNAL(valueChanged(int)) );
+ CM( malUserName, SIGNAL(textChanged(const QString &)) );
+ CM( malPassword, SIGNAL(textChanged(const QString &)) );
+#undef CM
+}
+
+MALWidgetSetup::~MALWidgetSetup()
+{
+ FUNCTIONSETUP;
+}
+
+/* virtual */ void MALWidgetSetup::commit()
+{
+ FUNCTIONSETUP;
+
+ MALConduitSettings::setSyncFrequency(
+ fConfigWidget->syncTime->id(fConfigWidget->syncTime->selected()));
+
+ // Proxy settings
+ MALConduitSettings::setProxyType(
+ fConfigWidget->proxyType->id(fConfigWidget->proxyType->selected()));
+ MALConduitSettings::setProxyServer( fConfigWidget->proxyServerName->currentText() );
+
+ if (fConfigWidget->proxyCustomPortCheck->isChecked() )
+ {
+ MALConduitSettings::setProxyPort( fConfigWidget->proxyCustomPort->value());
+ }
+ else
+ {
+ MALConduitSettings::setProxyPort(0);
+ }
+ MALConduitSettings::setProxyUser( fConfigWidget->proxyUserName->text() );
+ MALConduitSettings::setProxyPassword( fConfigWidget->proxyPassword->password() );
+
+ // MAL Server settings (not yet possible!!!)
+ MALConduitSettings::setMALServer( fConfigWidget->malServerName->currentText() );
+
+ if (fConfigWidget->malCustomPortCheck->isChecked() )
+ {
+ MALConduitSettings::setMALPort( fConfigWidget->malCustomPort->value());
+ }
+ else
+ {
+ MALConduitSettings::setMALPort(0);
+ }
+ MALConduitSettings::setMALUser( fConfigWidget->malUserName->text() );
+ MALConduitSettings::setMALPassword( fConfigWidget->malPassword->text() );
+
+ MALConduitSettings::self()->writeConfig();
+ unmodified();
+}
+
+
+
+/* virtual */ void MALWidgetSetup::load()
+{
+ FUNCTIONSETUP;
+ MALConduitSettings::self()->readConfig();
+
+ fConfigWidget->syncTime->setButton( MALConduitSettings::syncFrequency() );
+
+ // Proxy settings
+ fConfigWidget->proxyType->setButton(MALConduitSettings::proxyType());
+ fConfigWidget->proxyServerName->setEditText(MALConduitSettings::proxyServer());
+
+ int proxyPortNr=MALConduitSettings::proxyPort();
+ if (proxyPortNr>0 && proxyPortNr<65536)
+ {
+ fConfigWidget->proxyCustomPortCheck->setChecked(true);
+ fConfigWidget->proxyCustomPort->setEnabled(true);
+ fConfigWidget->proxyCustomPort->setValue(proxyPortNr);
+ }
+ fConfigWidget->proxyUserName->setText(MALConduitSettings::proxyUser());
+ fConfigWidget->proxyPassword->setText(QString::null);
+ fConfigWidget->proxyPassword->insert(MALConduitSettings::proxyPassword());
+
+#ifdef DEBUG
+ DEBUGKPILOT << fname << ": Got proxy password <"
+ << MALConduitSettings::proxyPassword()
+ << "> set Text <"
+ << fConfigWidget->proxyPassword->text()
+ << "> and Pwd <"
+ << fConfigWidget->proxyPassword->password()
+ << ">" << endl;
+#endif
+
+ // MAL Server settings (not yet possible!!!)
+ fConfigWidget->malServerName->setEditText(MALConduitSettings::mALServer());
+
+ int malPortNr=MALConduitSettings::mALPort();
+ if (malPortNr>0 && malPortNr<65536)
+ {
+ fConfigWidget->malCustomPortCheck->setChecked(true);
+ fConfigWidget->malCustomPort->setEnabled(true);
+ fConfigWidget->malCustomPort->setValue(proxyPortNr);
+ }
+ fConfigWidget->malUserName->setText(MALConduitSettings::mALUser());
+ fConfigWidget->malPassword->setText(MALConduitSettings::mALPassword());
+ unmodified();
+}
+
+/* static */ ConduitConfigBase *MALWidgetSetup::create(QWidget *w, const char *n)
+{
+ return new MALWidgetSetup(w,n);
+}
+
diff --git a/kpilot/conduits/malconduit/mal-setup.h b/kpilot/conduits/malconduit/mal-setup.h
new file mode 100644
index 000000000..78b6a0ee2
--- /dev/null
+++ b/kpilot/conduits/malconduit/mal-setup.h
@@ -0,0 +1,54 @@
+#ifndef _MAL_SETUP_H
+#define _MAL_SETUP_H
+/* mal-setup.h KPilot
+**
+** Copyright (C) 2002 by Reinhold Kainhofer
+**
+** This file defines the widget and behavior for the config dialog
+** of the mal conduit.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+**
+**
+** Specific permission is granted for this code to be linked to libmal
+** (this is necessary because the libmal license is not GPL-compatible).
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include "plugin.h"
+
+class MALWidget;
+
+class MALWidgetSetup : public ConduitConfigBase
+{
+Q_OBJECT
+public:
+ MALWidgetSetup(QWidget *,const char *);
+ virtual ~MALWidgetSetup();
+ virtual void load();
+ virtual void commit();
+ static ConduitConfigBase *create(QWidget *, const char *);
+private:
+ MALWidget *fConfigWidget;
+} ;
+
+
+#endif
diff --git a/kpilot/conduits/malconduit/mal-setup_dialog.ui b/kpilot/conduits/malconduit/mal-setup_dialog.ui
new file mode 100644
index 000000000..8814d190c
--- /dev/null
+++ b/kpilot/conduits/malconduit/mal-setup_dialog.ui
@@ -0,0 +1,634 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>MALWidget</class>
+<author>Reinhold Kainhofer</author>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>MalWidget</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>534</width>
+ <height>505</height>
+ </rect>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QTabWidget" row="0" column="0">
+ <property name="name">
+ <cstring>tabWidget</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>General</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QButtonGroup" row="0" column="0">
+ <property name="name">
+ <cstring>syncTime</cstring>
+ </property>
+ <property name="title">
+ <string>Sync</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Select how often AvantGo should be synchronised</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QRadioButton" row="0" column="0">
+ <property name="name">
+ <cstring>RadioButton1</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>&amp;Every sync</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Select this option to synchronize with the MAL server on every HotSync. To perform a successful synchronization, you need to have access to the MAL server during the HotSync.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="1" column="0">
+ <property name="name">
+ <cstring>RadioButton1_2</cstring>
+ </property>
+ <property name="text">
+ <string>Once per &amp;hour</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string></string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Select this option to synchronize with the MAL server on every HotSync that is at least one hour after the previous MAL sync. To perform a successful synchronization, you need to have access to the MAL server during the HotSync.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="2" column="0">
+ <property name="name">
+ <cstring>RadioButton1_3</cstring>
+ </property>
+ <property name="text">
+ <string>Once a &amp;day</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Select this option to synchronize with the MAL server on every HotSync that is at least one day after the previous MAL sync. To perform a successful synchronization, you need to have access to the MAL server during the HotSync.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="3" column="0">
+ <property name="name">
+ <cstring>RadioButton1_4</cstring>
+ </property>
+ <property name="text">
+ <string>Once a &amp;week</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Select this option to synchronize with the MAL server on every HotSync that is at least one week after the previous MAL sync. To perform a successful synchronization, you need to have access to the MAL server during the HotSync.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="4" column="0">
+ <property name="name">
+ <cstring>RadioButton1_5</cstring>
+ </property>
+ <property name="text">
+ <string>Once a &amp;month</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Select this option to synchronize with the MAL server on every HotSync that is at least one month after the previous MAL sync. To perform a successful synchronization, you need to have access to the MAL server during the HotSync.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <spacer row="1" column="0">
+ <property name="name">
+ <cstring>Spacer3</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>
+ </grid>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Proxy</string>
+ </attribute>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QButtonGroup">
+ <property name="name">
+ <cstring>proxyType</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>GroupBoxPanel</enum>
+ </property>
+ <property name="title">
+ <string>Proxy Type</string>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>RadioButton8</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;No proxy</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Select this option if you do not want KPilot to use a proxy server. Use this option if you connect to the internet directly.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>RadioButton8_2</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;HTTP proxy</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Select this option if you want KPilot to use a HTTP proxy.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>RadioButton8_2_2</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;SOCKS proxy</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Select this option if you want KPilot to use a SOCKS proxy.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>proxyServerInformation</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="title">
+ <string>Server Information</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <spacer row="1" column="2">
+ <property name="name">
+ <cstring>Spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QCheckBox" row="1" column="0">
+ <property name="name">
+ <cstring>proxyCustomPortCheck</cstring>
+ </property>
+ <property name="text">
+ <string>Custom &amp;port:</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Check this box to use a non-standard proxy port.</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>TextLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Ser&amp;ver name:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>proxyServerName</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;If you selected HTTP or SOCKS proxy, type the address of the proxy server to use here, in the form &lt;i&gt;foo.bar.com&lt;/i&gt; (not &lt;i&gt;http://foo.bar.com&lt;/i&gt; or &lt;i&gt;http://foo.bar.com:8080&lt;/i&gt;).&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="KHistoryCombo" row="0" column="1" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>proxyServerName</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;If you selected HTTP or SOCKS proxy, type the address of the proxy server to use here, in the form &lt;i&gt;foo.bar.com&lt;/i&gt; (not &lt;i&gt;http://foo.bar.com&lt;/i&gt; or &lt;i&gt;http://foo.bar.com:8080&lt;/i&gt;).&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="KIntNumInput" row="1" column="1">
+ <property name="name">
+ <cstring>proxyCustomPort</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="value">
+ <number>80</number>
+ </property>
+ <property name="minValue">
+ <number>0</number>
+ </property>
+ <property name="maxValue">
+ <number>65535</number>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Enter the port you want KPilot to use when connecting to your proxy server here.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="KPasswordEdit" row="5" column="1" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>proxyPassword</cstring>
+ </property>
+ <property name="echoMode">
+ <enum>Password</enum>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;If your proxy requires authentication, enter your password here.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QLineEdit" row="4" column="1" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>proxyUserName</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;If your proxy requires authentication, enter your username here.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="5" column="0">
+ <property name="name">
+ <cstring>TextLabel2_2</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Password:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>proxyPassword</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="4" column="0">
+ <property name="name">
+ <cstring>TextLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;User name:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>proxyUserName</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;If your proxy requires authentication, enter your username here.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="Line" row="3" column="0" rowspan="1" colspan="3">
+ <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="QLineEdit" row="2" column="1" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>proxyExclude</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Enter a list of MAL servers that do not need the use of a proxy here, separated with commas, e.g: &lt;br&gt;&lt;i&gt;localhost,127.0.0.1,.lan&lt;/i&gt;&lt;qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="2" column="0">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>N&amp;o proxy for:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>proxyExclude</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Enter a list of MAL servers that do not need the use of a proxy here, separated with commas, e.g: &lt;br&gt;&lt;i&gt;localhost,127.0.0.1,.lan&lt;/i&gt;&lt;qt&gt;</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>Spacer3_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>70</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>MAL Server</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QGroupBox" row="1" column="0">
+ <property name="name">
+ <cstring>GroupBox1_2</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="title">
+ <string>MAL Server Information</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLabel" row="0" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>TextLabel1_2</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;MAL server name:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>malServerName</cstring>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="1" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>malCustomPortCheck</cstring>
+ </property>
+ <property name="text">
+ <string>Custom &amp;port:</string>
+ </property>
+ </widget>
+ <widget class="KIntNumInput" row="1" column="2">
+ <property name="name">
+ <cstring>malCustomPort</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="value">
+ <number>80</number>
+ </property>
+ <property name="minValue">
+ <number>0</number>
+ </property>
+ <property name="maxValue">
+ <number>65535</number>
+ </property>
+ </widget>
+ <spacer row="1" column="3">
+ <property name="name">
+ <cstring>Spacer2_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="KHistoryCombo" row="0" column="2" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>malServerName</cstring>
+ </property>
+ </widget>
+ <widget class="QLineEdit" row="3" column="1" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>malUserName</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="4" column="0">
+ <property name="name">
+ <cstring>TextLabel2_2_2</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Password:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>malPassword</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="3" column="0">
+ <property name="name">
+ <cstring>textLabel</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;User name:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>malUserName</cstring>
+ </property>
+ </widget>
+ <widget class="Line" row="2" column="0" rowspan="1" colspan="4">
+ <property name="name">
+ <cstring>Line1_2</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="KPasswordEdit" row="4" column="1" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>malPassword</cstring>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <spacer row="2" column="0">
+ <property name="name">
+ <cstring>Spacer5</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>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>TextLabel1_3</cstring>
+ </property>
+ <property name="text">
+ <string>&lt;qt&gt;There is currently &lt;b&gt;no way to set server parameters on the desktop&lt;/b&gt;; you need to use the &lt;i&gt;MobileLink&lt;/i&gt; or &lt;i&gt;AGConnect&lt;/i&gt; application on the handheld device. &lt;/qt&gt;</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </widget>
+ </grid>
+</widget>
+<connections>
+ <connection>
+ <sender>RadioButton8</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>proxyServerInformation</receiver>
+ <slot>setDisabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>RadioButton8_2</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>proxyServerInformation</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>RadioButton8_2_2</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>proxyServerInformation</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>proxyCustomPortCheck</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>proxyCustomPort</receiver>
+ <slot>setEditFocus(bool)</slot>
+ </connection>
+ <connection>
+ <sender>proxyCustomPortCheck</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>proxyCustomPort</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>malCustomPortCheck</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>malCustomPort</receiver>
+ <slot>setEditFocus()</slot>
+ </connection>
+ <connection>
+ <sender>malCustomPortCheck</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>malCustomPort</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+</connections>
+<tabstops>
+ <tabstop>tabWidget</tabstop>
+</tabstops>
+<layoutdefaults spacing="6" margin="11"/>
+<includes>
+ <include location="global" impldecl="in implementation">klineedit.h</include>
+ <include location="global" impldecl="in implementation">knuminput.h</include>
+</includes>
+</UI>
diff --git a/kpilot/conduits/malconduit/mal_conduit.desktop b/kpilot/conduits/malconduit/mal_conduit.desktop
new file mode 100644
index 000000000..47bfe45b0
--- /dev/null
+++ b/kpilot/conduits/malconduit/mal_conduit.desktop
@@ -0,0 +1,96 @@
+[Desktop Entry]
+Type=Service
+Name=MAL (AvantGo) Conduit
+Name[af]=MAL (AvantGo) pad
+Name[ca]=Conducte MAL (AvantGo)
+Name[cs]=Propojení s AvantGo
+Name[cy]=Cwndid MAL (AvantGo)
+Name[de]=MAL- (AvantGo) Abgleich (Conduit)
+Name[el]=ΣÏνδεσμος MAL (AvantGo)
+Name[eo]=MAL (AvantGo) Kanalo
+Name[es]=Conducto MAL (AvantGo)
+Name[et]=MAL (AvantGo) kanal
+Name[eu]=MAL (AvantGo) kanala
+Name[fa]=لولۀ MAL (AvantGo)
+Name[fi]=MAL (AvantGo)- yhdyskäytävä
+Name[fr]=MAL (AvantGo) Canal
+Name[ga]=Seoladán MAL (AvantGo)
+Name[gl]=Conducto MAL (AvantGo)
+Name[he]=ממשק AvantGo) MAL)
+Name[hi]=à¤à¤®à¤à¤à¤² (AvantGo) कनà¥à¤¡à¥à¤¯à¥‚इट
+Name[hu]=MAL- (AvantGo) csatoló
+Name[is]=MAL (AvantGo)-rás
+Name[it]=Conduit MAL (AvantGo)
+Name[ja]=MAL (AvantGo) コンジット
+Name[ka]=áƒáƒ áƒ®áƒ˜ MAL (AvantGo)
+Name[kk]=MAL (AvantGo) арнаÑÑ‹
+Name[km]=បំពង់ MAL (AvantGo)
+Name[lt]=MAL (AvantGo) kanalas
+Name[ms]=Saluran MAL (AvantGo)
+Name[nb]=MAL (AvantGo) kanal
+Name[nds]=MAL(AvantGo)-Synkroniseren
+Name[ne]=MAL (AvantGo) कनà¥à¤¡à¥à¤¯à¥à¤Ÿ
+Name[nn]=MAL-kopling (AvantGo)
+Name[nso]=Conduit ya MAL (AvantGo)
+Name[pl]=ÅÄ…cznik do MAL (AvantGo)
+Name[pt]=Conduta MAL (AvantGo)
+Name[pt_BR]=Conduto MAL (AvantGo)
+Name[ro]=Conductă MAL (AvantGo)
+Name[ru]=Канал MAL (AvantGo)
+Name[sk]=Spojka MAL (AvantGo)
+Name[sl]=Veznik MAL (AvantGo)
+Name[sr]=MAL (AvantGo) провод
+Name[sr@Latn]=MAL (AvantGo) provod
+Name[sv]=MAL (AvantGo)-kanal
+Name[ta]=MAL (AvantGo) காபà¯à®ªà¯à®•à¯ கà¯à®´à®¾à®¯à¯
+Name[tg]=Канали MAL (AvantGo)
+Name[tr]=MAL (AvantGo) Kanalı
+Name[uk]=Ðкведук MAL (AvantGo)
+Name[zh_CN]=MAL (AvantGo) 管é“
+Comment=Syncronize AvantGo (or generally a MAL server's content) to the handheld. This allows you to view web-pages offline on the handheld, like your cinema or TV schedule, or any other web page.
+Comment[af]=Sinkroniseer AvantGo (MAL bediener inhoud) informasie na die draagbare toestel. Dit maak dit moontlik om aflyn na web blaaie, soos TV en fliek skedules, te kyk.
+Comment[bg]=Синхронизиране на AvantGo към мобилно уÑтройÑтво. Тази приÑтавка ви позволÑва да разглеждате уеб Ñтраници без връзка Ñ ÐœÑ€ÐµÐ¶Ð°Ñ‚Ð°.
+Comment[ca]=Sincronitza AvantGo (o el contingut d'un servidor MAL en general) a l'agenda electrònica. Això us permet veure pàgines web a l'agenda electrònica en mode desconnectat, com ara la programació de TV o cinema o qualsevol altra pàgina web.
+Comment[cs]=Synchronizace AvantGo (nebo obecně obsahu MAL serverů) s PDA. To umožňuje offline prohlížení stránek v PDA např. TV programů, programů kin a mnoha dalších stránek.
+Comment[da]=Synkronisér AvantGo (eller mere alment indholdet på en MAL-server) med den håndholdte. Det lader dig kigge på nedsider offline på den håndholdte, såsom biografer eller tv-programmer, eller en hvilken som helst anden netside.
+Comment[de]=Gleicht AvantGo (oder allgemein den Inhalt eines MAL-Servers) mit dem Taschencomputer ab. So können Sie z. B. Internetseiten ohne Internetverbindung auf dem Taschencomputer lesen, zum Beispiel einen Kinoplan oder die aktuelle Programmzeitschrift.
+Comment[el]=ΣυγχÏονισμός ενός AvantGo (ή γενικότεÏα τα πεÏιεχόμενα ενός εξυπηÏετητή MAL) με τον υπολογιστή παλάμης. Αυτό σας επιτÏέπει να βλέπετε ιστοσελίδες στον υπολογιστή παλάμης χωÏίς να είστε συνδεδεμένοι, όπως το Ï€ÏόγÏαμμα των κινηματογÏάφων ή της τηλεόÏασης, ή οποιαδήποτε άλλη ιστοσελίδα.
+Comment[en_GB]=Syncronise AvantGo (or generally a MAL server's content) to the handheld. This allows you to view web-pages offline on the handheld, like your cinema or TV schedule, or any other web page.
+Comment[es]=Sincroniza AvantGo (o más genéricamente, el contenido de un servidor MAL) con la agenda electrónica. Le permite ver páginas web en la agenda electrónica sin estar conectado, como la programación de televisión o la cartelera de cine, o cualquier otra página web.
+Comment[et]=See kanal sünkroniseerib AvantGo (või üldisemalt MAL serveri sisu) pihuarvutiga. See võimaldab vaadata veebilehekülgi pihuseadmelt ilma võrguühendusega, näiteks uurida kino- või telekava või mis tahes muud huvipakkuvat veebilehekülge.
+Comment[eu]=Sinkronizatu AvantGo (edo orokorrean MAL zerbitzariaren edukina) agenda elektronikora. Honek web-orriak agendan konexio gabe ikusteko aukera ematen dizu, zure zine edo TB antolatzailean bezala, edo beste web orri bat bezala.
+Comment[fa]=همگام‌سازی AvantGo (یا عموماً محتوای کارساز MAL) با دستی. به شما اجازه می‌دهد Ú©Ù‡ صÙحات وب برون‌خطی روی دستی، مانند برنامۀ سینما یا تلویزیون شما، یا هر صÙحه وب دیگری را مشاهده کنید.
+Comment[fi]=Synkronoi AvantGo (tai yleisesti MAL-palvelimen sisältö) taskutietokoneeseen. Tämä mahdollistaa web-sivujen lukemisen offline-tilassa (esim. elokuva- tai tv-ohjelmasivujen).
+Comment[fr]=Synchronise AvantGo (ou plus généralement tout serveur MAL) avec votre Palm. Ceci vous permet de consulter des pages Web hors ligne sur votre Palm, comme des programmes TV, Cinéma ou n'importe quelle page Web.
+Comment[fy]=Avantgo mei de handheld syngronosearje (of eins mei de ynhâld fan in g MAL-tsjinner). Dit makket it mooglik om in webside sûnder ferbining te besjen op jo handheld. Dit is hanjnich foar in soad saken lykas de TV-gids.
+Comment[gl]=Sincronizar AvantGo (ou xeralmente o contido dun servidor MAL) co aparello portátil. Isto permite ver as páxinas web fóra de liña no aparello portátil, como a programación do cine ou da TV, ou calquera outra páxina web.
+Comment[hu]=AvantGo (vagy MAL-kiszolgáló) adatainak szinkronizálása a kézi számítógéppel. Lehetővé teszi weboldalak offline módban való megtekintését, például a mozi- vagy tévéműsort, vagy bármi mást.
+Comment[is]=Samstillir AvantGo (eða venjulega innihald MAL þjóns) við lófatölvuna. Þetta gerir þér kleyft að skoða vefsíður þegar þú ert ótengd(ur) vefnum, t.d. kvikmynda eða sjónvarpsdagskrá.
+Comment[it]=Sincronizza AvantGo (o il contenuto di un generico server MAL) con il palmare. In questo modo potrai visualizzare le pagine web offline sul palmare come per esempio la programmazione di un cinema o una TV o qualsiasi altra pagina web.
+Comment[ja]=AvantGo (ã¾ãŸã¯ä¸€èˆ¬ã« MAL サーãƒã®ã‚³ãƒ³ãƒ†ãƒ³ãƒ„) ã¨ãƒãƒ³ãƒ‰ãƒ˜ãƒ«ãƒ‰ã‚’åŒæœŸã•ã›ã¾ã™ã€‚ã“ã‚Œã«ã‚ˆã‚Šã€ãƒãƒ³ãƒ‰ãƒ˜ãƒ«ãƒ‰ã§æ˜ ç”»ã‚„ TV 番組表ã€ãã®ä»–ã®ã‚¦ã‚§ãƒ–ページをオフラインã§é–²è¦§ã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚
+Comment[ka]= AvantGo-ს სინქრáƒáƒœáƒ˜áƒ–áƒáƒªáƒ˜áƒ (ძირითáƒáƒ“áƒáƒ“ MAL სერვერების შემáƒáƒ“გენლáƒáƒ‘ით) პáƒáƒ áƒ¢áƒáƒ¢áƒ˜áƒ£áƒš მáƒáƒ¬áƒ§áƒáƒ‘ილáƒáƒ‘áƒáƒ¡áƒ—áƒáƒœ. ეს ვებ-გვერდების áƒáƒ•áƒ¢áƒáƒœáƒáƒ›áƒ˜áƒ£áƒ  რეჟიმში დáƒáƒ—ვáƒáƒšáƒ˜áƒ”რების სáƒáƒ¨áƒ£áƒáƒšáƒ”ბáƒáƒ¡ იძლევáƒ,მáƒáƒ’.: თქვენი კინრáƒáƒœ ტელე პრáƒáƒ’რáƒáƒ›áƒ, áƒáƒœ სხვრვებ-გვერდები.
+Comment[kk]=AvantGo (немеÑе жалпы MAL Ñервердің мазмұнын) қалта құрылғымен қадамдаÑтыру арнаÑÑ‹. Бұл Ñол құрылғыда кино, ТВ кеÑтеңізді немеÑе баÑқа веб парақтарды желіге қоÑылмай көруге мүмкіндік береді.
+Comment[km]=ធ្វើ​សមកាលកម្ម AvantGo (ជាទូទៅ​គឺ មាážáž·áž€áž¶â€‹ážšáž”ស់​ម៉ាស៊ីន​បម្រើ MAL) ទៅ​នឹង​ឧបករណáŸâ€‹áž™áž½ážšâ€‹ážŠáŸƒÂ áŸ” វា​អនុញ្ញាážâ€‹áž²áŸ’យ​អ្នក​មើល​ទំពáŸážšâ€‹áž”ណ្ដាញ (កាលវិភាគ​រោង​ភាពយន្ហឬ ទូរទស្សនáŸ...) នៅ​ក្រៅ​បណ្ដាញ នៅ​លើ​ឧបករណáŸâ€‹áž™áž½ážšâ€‹ážŠáŸƒâ€‹ážšáž”ស់​អ្នក ។
+Comment[lt]=Sinchronizuoti AvantGo (ar MAL serverio turinį apskritai) su nešiojamu įrenginiu. Tai leis jums peržiūrėti žiniatinklio puslapius nešiojamame įrenginyje, tokius kaip kino teatro ar TV programas, bei bet kokį kitą puslapį, neprisijungus prie Interneto.
+Comment[ms]=Mensegerakkan AvantGo (atau kandungan pelayan MAL secara umum) ke komputer telapak. Ini membolehkan anda memaparkan laman web di luar talian pada komputer telapak, seperti pawagam atau jadual TV, atau laman web lain.
+Comment[nb]=Synkroniser AvantGo (eller generelt innholdet i en MAL-tjener) til PDA-en. På denne måten kan du se nettsider frakoblet på PDA-en. slik som TV-programlister, kinoprogrammer eller andre nettsider.
+Comment[nds]=Synkroniseert den Inholt vun AvantGo oder jichtenseen anner MAL-Server ("Mobile Application Link") mit den Handreekner. So kannst Du Nettsieden ahn Verbinnen op den Handreekner ankieken, t.B. dat Kino- oder Feernsehprogramm.
+Comment[ne]=AvantGo (वा साधारणतया à¤à¤‰à¤Ÿà¤¾ MAL सरà¥à¤­à¤°à¤•à¥‹ सामागà¥à¤°à¥€) हà¥à¤¯à¤¾à¤¨à¥à¤¡à¤¹à¥‡à¤²à¥à¤¡à¤®à¤¾ समकà¥à¤°à¤®à¤£ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥ । यसले तपाईà¤à¤²à¤¾à¤ˆ वेब पृषà¥à¤ , जसà¥à¤¤à¥ˆ: सिनेमा वा टी भी कारà¥à¤¯à¤¤à¤¾à¤²à¤¿à¤•à¤¾, वा अनà¥à¤¯ कà¥à¤¨à¥ˆ वेब पृषà¥à¤  हà¥à¤¯à¤¾à¤¨à¥à¤¡à¤¹à¥‡à¤²à¥à¤¡à¤•à¥‹ अफलाईनमा हेरà¥à¤¨ अनà¥à¤®à¤¤à¤¿ दिनà¥à¤› ।
+Comment[nl]=Avantgo met de handheld synchroniseren (of eigenlijk met de inhoud van een MAL-server). Dit maakt het mogelijk om een webpagina offline op uw handheld te bekijken. Dit is handig voor allerlei zaken als bijvoorbeeld de TV-gids.
+Comment[pl]=Synchronizuje AvantGo (lub ogólnie zawartość serwera MAL) z palmtopem. Pozwala to przeglądać bez połączenia z siecią strony WWW na palmtopie, np. repertuar kin lub program telewizyjny.
+Comment[pt]=Sincroniza o AvantGo (ou, genericamente, o conteúdo de um servidor de MAL) para o dispositivo móvel. Isto permite-lhe ver as páginas Web no dispositivo móvel sem estar ligado, como o seu horário de cinema ou TV ou ainda qualquer outra página Web.
+Comment[pt_BR]=Sincroniza AvantGo (ou geralmente o conteúodo de um servidor MAL) com o handheld. Isto permite que você visualize páginas web offline no handheld, por exemplo a grade do cinema ou TV, ou qualquer outra página.
+Comment[ru]=Ð¡Ð¸Ð½Ñ…Ñ€Ð¾Ð½Ð¸Ð·Ð°Ñ†Ð¸Ñ AvantGo (Ñодержимого Ñерверов MAL) Ñ ÐšÐŸÐš. Это позволит вам проÑматривать веб-Ñтраницы без Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ðº Интернет.
+Comment[sk]=Synchronizuje AvantGo (alebo vÅ¡eobecne obsah MAL servera) s ruÄným zariadením. Toto umožní vidieÅ¥ webovské stránky bez pripojenia na ruÄnom zariadení, ako sú programy kina alebo TV, alebo hociakej webovskej stránky.
+Comment[sl]=Uskladi AvantGo (oziroma v sploÅ¡nem vsebino strežnika MAL) na roÄnem raÄunalniku. S tem si lahko na njem ogledujete spletne strani brez povezave, kot so razpored kino predstav ali pa TV spored ali pa katerokoli drugo spletno stran.
+Comment[sr]=Синхронизује AvantGo (или уопштено Ñадржај MAL Ñервера) Ñа ручним рачунаром. Ово вам омогућава да на ручном рачунару прегледате веб Ñтране ван везе, као биоÑкопÑки или ТВ програм, или било коју другу веб Ñтрану.
+Comment[sr@Latn]=Sinhronizuje AvantGo (ili uopÅ¡teno sadržaj MAL servera) sa ruÄnim raÄunarom. Ovo vam omogućava da na ruÄnom raÄunaru pregledate veb strane van veze, kao bioskopski ili TV program, ili bilo koju drugu veb stranu.
+Comment[sv]=Synkronisera AvantGo (eller mer allmänt innehållet på en MAL-server) med handdatorn. Det låter dig titta på webbsidor i nerkopplat läge på handdatorn, som bio eller tv-program, eller vilken annan webbsida som helst.
+Comment[ta]=AvantGo஠கையில௠வைதà¯à®¤à®¿à®°à¯à®ªà¯à®ªà®¤à®¿à®²à¯ கூடà¯à®Ÿà®¿à®£à¯ˆà®•à¯à®•à®µà¯à®®à¯ (அலà¯à®²à®¤à¯ ஒர௠MAL சேவகனின௠உளà¯à®³à®Ÿà®•à¯à®•à®¤à¯à®¤à®¿à®±à¯à®•à¯). இதனà¯à®®à¯‚லம௠கையில௠இரà¯à®ªà¯à®ªà®¤à®¿à®²à¯‡à®¯à¯‡ வலைபà¯à®ªà®•à¯à®•à®™à¯à®•à®³à¯ˆ பாரà¯à®•à¯à®•à®²à®¾à®®à¯, அதாவத௠சினிமா, தொலைகà¯à®•à®¾à®Ÿà¯à®Ÿà®¿ அடà¯à®Ÿà®µà¯à®£à¯ˆ, அலà¯à®²à®¤à¯ à®à®¤à®¾à®µà®¤à¯ ஒர௠வலைபà¯à®ªà®•à¯à®•à®®à¯.
+Comment[tr]=AvantGo içeriğini (ya da genel olarak MAL sunucuları içeriğini) el bilgisayarı ile birleştirir. Bu, web sayfalarını el bilgisayarınızda çevirim dışı olarak görüntülemenizi sağlar.
+Comment[uk]=Ð¡Ð¸Ð½Ñ…Ñ€Ð¾Ð½Ñ–Ð·Ð°Ñ†Ñ–Ñ AvantGo (або вміÑÑ‚ Ñерверів MAL) на кишеньковий приÑтрій . Це дозволÑÑ” переглÑдати веб-Ñторінки на кишеньковому приÑтрої без з'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð· Інтернетом.
+Comment[zh_CN]=å°† AvantGo(或 MAL æœåŠ¡å™¨çš„内容)åŒæ­¥åˆ°æ‰‹æŒè®¾å¤‡ä¸­ã€‚è¿™å…许您在手æŒè®¾å¤‡ä¸­è„±æœºæŸ¥çœ‹ Web 页,比如影讯ã€ç”µè§†èŠ‚目时间表或任何其它网页。
+Comment[zh_TW]=åŒæ­¥ AvantGo (或通常為一 MAL 伺æœå™¨å…§å®¹) 與 handheld。
+Implemented=file
+ServiceTypes=KPilotConduit
+X-KDE-Library=conduit_mal
diff --git a/kpilot/conduits/malconduit/malconduit.kcfg b/kpilot/conduits/malconduit/malconduit.kcfg
new file mode 100644
index 000000000..146f7869c
--- /dev/null
+++ b/kpilot/conduits/malconduit/malconduit.kcfg
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
+ http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
+ <kcfgfile name="kpilot_malconduitrc"/>
+ <group name="General">
+ <entry name="LastMALSync" key="Last MAL Sync" type="DateTime">
+ <default>QDateTime( QDate(1970,1,1), QTime(0,0,0) )</default>
+ </entry>
+
+ <entry name="SyncFrequency" key="Sync Frequency" type="Enum">
+ <choices>
+ <choice name="eEverySync"/>
+ <choice name="eEveryHour"/>
+ <choice name="eEveryDay"/>
+ <choice name="eEveryWeek"/>
+ <choice name="eEveryMonth"/>
+ </choices>
+ <default>eEverySync</default>
+ </entry>
+
+ <entry name="ProxyType" key="Proxy Type" type="Enum">
+ <choices>
+ <choice name="eProxyNone"/>
+ <choice name="eProxyHTTP"/>
+ <choice name="eProxySOCKS"/>
+ </choices>
+ <default>eProxyNone</default>
+ </entry>
+ <entry name="ProxyServer" key="Proxy Server" type="String">
+ <default></default>
+ </entry>
+ <entry name="ProxyPort" key="Proxy Port" type="UInt">
+ <default>0</default>
+ </entry>
+ <entry name="ProxyUser" key="Proxy User" type="String">
+ <default></default>
+ </entry>
+ <entry name="ProxyPassword" key="Proxy Password" type="Password">
+ <default></default>
+ </entry>
+ <entry name="MALServer" key="MAL Server" type="String">
+ <default>sync.avantgo.com</default>
+ </entry>
+ <entry name="MALPort" key="MAL Port" type="UInt">
+ <default>0</default>
+ </entry>
+ <entry name="MALUser" key="MAL User" type="String">
+ <default></default>
+ </entry>
+ <entry name="MALPassword" key="MAL Password" type="String">
+ <default></default>
+ </entry>
+ </group>
+</kcfg>
diff --git a/kpilot/conduits/malconduit/malconduitSettings.kcfgc b/kpilot/conduits/malconduit/malconduitSettings.kcfgc
new file mode 100644
index 000000000..d4254c41b
--- /dev/null
+++ b/kpilot/conduits/malconduit/malconduitSettings.kcfgc
@@ -0,0 +1,7 @@
+File=malconduit.kcfg
+ClassName=MALConduitSettings
+Singleton=true
+ItemAccessors=true
+Mutators=true
+GlobalEnums=true
+SetUserTexts=true
diff --git a/kpilot/conduits/memofileconduit/CMakeLists.txt b/kpilot/conduits/memofileconduit/CMakeLists.txt
new file mode 100644
index 000000000..56994570f
--- /dev/null
+++ b/kpilot/conduits/memofileconduit/CMakeLists.txt
@@ -0,0 +1,44 @@
+include_directories(
+ ${CMAKE_CURRENT_BINARY_DIR}
+)
+
+set(conduit_memofile_SRCS
+ memofile-factory.cc
+ memofile.cc
+ memofiles.cc
+ memofile-conduit.cc
+)
+
+set(conduit_memofile_UIS
+ setup_base.ui
+)
+
+set(conduit_memofile_KCFGS
+ memofileSettings.kcfgc
+)
+
+kde3_add_kcfg_files(conduit_memofile_SRCS ${conduit_memofile_KCFGS})
+kde3_add_ui_files(conduit_memofile_SRCS ${conduit_memofile_UIS})
+kde3_automoc(${conduit_memofile_SRCS})
+add_library(conduit_memofile SHARED ${conduit_memofile_SRCS})
+
+set_target_properties(
+ conduit_memofile PROPERTIES LOCATION ${KDE3_PLUGIN_INSTALL_DIR}
+ INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/lib
+ PREFIX ""
+)
+
+kde3_install_libtool_file(conduit_memofile)
+
+install(
+ TARGETS conduit_memofile
+ LIBRARY DESTINATION ${KDE3_PLUGIN_INSTALL_DIR}
+)
+
+install(
+ FILES memofile-conduit.desktop DESTINATION ${KDE3_SERVICES_DIR}
+)
+
+install(
+ FILES memofileconduit.kcfg DESTINATION ${KDE3_KCFG_DIR}
+)
diff --git a/kpilot/conduits/memofileconduit/Makefile.am b/kpilot/conduits/memofileconduit/Makefile.am
new file mode 100644
index 000000000..e4a244b51
--- /dev/null
+++ b/kpilot/conduits/memofileconduit/Makefile.am
@@ -0,0 +1,16 @@
+INCLUDES= $(PISOCK_INCLUDE) -I$(top_srcdir)/kpilot/lib $(all_includes)
+
+METASOURCES = AUTO
+
+servicedir = $(kde_servicesdir)
+service_DATA = memofile-conduit.desktop
+
+kde_module_LTLIBRARIES = conduit_memofile.la
+
+
+conduit_memofile_la_SOURCES = memofileSettings.kcfgc setup_base.ui \
+ memofile-factory.cc memofile.cc memofiles.cc memofile-conduit.cc
+conduit_memofile_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries)
+conduit_memofile_la_LIBADD = ../../lib/libkpilot.la $(LIB_KDEUI) $(LIB_KFILE)
+
+kde_kcfg_DATA = memofileconduit.kcfg
diff --git a/kpilot/conduits/memofileconduit/design/SQD - copyHHToPC.jpg b/kpilot/conduits/memofileconduit/design/SQD - copyHHToPC.jpg
new file mode 100644
index 000000000..82cc11880
--- /dev/null
+++ b/kpilot/conduits/memofileconduit/design/SQD - copyHHToPC.jpg
Binary files differ
diff --git a/kpilot/conduits/memofileconduit/design/SQD - copyPCToHH.jpg b/kpilot/conduits/memofileconduit/design/SQD - copyPCToHH.jpg
new file mode 100644
index 000000000..ef4254d43
--- /dev/null
+++ b/kpilot/conduits/memofileconduit/design/SQD - copyPCToHH.jpg
Binary files differ
diff --git a/kpilot/conduits/memofileconduit/design/SQD - detailed load.jpg b/kpilot/conduits/memofileconduit/design/SQD - detailed load.jpg
new file mode 100644
index 000000000..4e0601f6a
--- /dev/null
+++ b/kpilot/conduits/memofileconduit/design/SQD - detailed load.jpg
Binary files differ
diff --git a/kpilot/conduits/memofileconduit/design/SQD - sync.jpg b/kpilot/conduits/memofileconduit/design/SQD - sync.jpg
new file mode 100644
index 000000000..91299ce07
--- /dev/null
+++ b/kpilot/conduits/memofileconduit/design/SQD - sync.jpg
Binary files differ
diff --git a/kpilot/conduits/memofileconduit/memofile-conduit.cc b/kpilot/conduits/memofileconduit/memofile-conduit.cc
new file mode 100644
index 000000000..1dc5fe386
--- /dev/null
+++ b/kpilot/conduits/memofileconduit/memofile-conduit.cc
@@ -0,0 +1,567 @@
+/* memofile-conduit.cc KPilot
+**
+** Copyright (C) 2004-2007 by Jason 'vanRijn' Kasper
+**
+** This file does the actual conduit work.
+*/
+
+/*
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU Lesser General Public License as published by
+** the Free Software Foundation; either version 2.1 of the License, or
+** (at your option) any later version.
+**
+** This 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 Lesser General Public License for more details.
+**
+** You should have received a copy of the GNU Lesser General Public License
+** along with this program in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+
+#include "options.h"
+
+// Only include what we really need:
+// First UNIX system stuff, then std C++,
+// then Qt, then KDE, then local includes.
+//
+//
+
+#include <time.h> // required by pilot-link includes
+
+#include <pi-memo.h>
+
+#include "pilotMemo.h"
+
+#include <qfile.h>
+#include <qdir.h>
+#include <qtextcodec.h>
+
+#include <kconfig.h>
+#include <kdebug.h>
+
+#include "pilotRecord.h"
+#include "pilotSerialDatabase.h"
+#include "memofile-factory.h"
+#include "memofile-conduit.h"
+#include "memofileSettings.h"
+
+
+/**
+ * Our workhorse. This is the main driver for the conduit.
+ */
+MemofileConduit::MemofileConduit(KPilotLink *d,
+ const char *n,
+ const QStringList &l) :
+ ConduitAction(d,n,l),
+ _DEFAULT_MEMODIR(QDir::homeDirPath() + CSL1("/MyMemos")),
+ fMemoAppInfo(0L),
+ _memofiles(0L)
+{
+ FUNCTIONSETUP;
+ fConduitName=i18n("Memofile");
+ fMemoList.setAutoDelete(true);
+}
+
+MemofileConduit::~MemofileConduit()
+{
+ FUNCTIONSETUP;
+ KPILOT_DELETE(_memofiles);
+}
+
+/* virtual */ bool MemofileConduit::exec()
+{
+ FUNCTIONSETUP;
+
+ setFirstSync( false );
+ // try new format first...
+ // DEBUGKPILOT << fname << ": trying new format database first." << endl;
+ bool _open = false;
+ /*
+ _open = openDatabases(CSL1("MemosDB-PMem"));
+ if(!_open) {
+ DEBUGKPILOT << fname << ": unable to open new format database. trying old one." << endl;
+ */
+ _open = openDatabases(CSL1("MemoDB"));
+ /*
+ } else {
+ DEBUGKPILOT << fname << ": able to open new format database." << endl;
+ }
+ */
+
+ if(!_open) {
+ emit logError(i18n("Unable to open the memo databases on the handheld."));
+ DEBUGKPILOT << fname << ": unable to open new or old format database." << endl;
+ return false;
+ }
+
+ readConfig();
+
+ if (! initializeFromPilot()) {
+ emit logError(i18n("Cannot initialize from pilot."));
+ return false;
+ }
+
+ _memofiles = new Memofiles(fCategories, *fMemoAppInfo,
+ _memo_directory, *fCtrHH);
+ if (! _memofiles || ! _memofiles->isReady()) {
+ emit logError(i18n("Cannot initialize the memo files from disk."));
+ return false;
+ }
+
+ fCtrPC->setStartCount(_memofiles->count());
+
+ setFirstSync( _memofiles->isFirstSync() );
+ addSyncLogEntry(i18n(" Syncing with %1.").arg(_memo_directory));
+
+ if ( (syncMode() == SyncAction::SyncMode::eCopyHHToPC) || _memofiles->isFirstSync() ) {
+ addSyncLogEntry(i18n(" Copying Pilot to PC..."));
+ DEBUGKPILOT << fname << ": copying Pilot to PC." << endl;
+ copyHHToPC();
+ } else if ( syncMode() == SyncAction::SyncMode::eCopyPCToHH ) {
+ DEBUGKPILOT << fname << ": copying PC to Pilot." << endl;
+ addSyncLogEntry(i18n(" Copying PC to Pilot..."));
+ copyPCToHH();
+ } else {
+ DEBUGKPILOT << fname << ": doing regular sync." << endl;
+ addSyncLogEntry(i18n(" Doing regular sync..."));
+ sync();
+ }
+
+ cleanup();
+
+ return delayDone();
+}
+
+bool MemofileConduit::readConfig()
+{
+ FUNCTIONSETUP;
+
+ QString dir(MemofileConduitSettings::directory());
+ if (dir.isEmpty()) {
+ dir = _DEFAULT_MEMODIR;
+
+ DEBUGKPILOT << fname
+ << ": no directory given to us. defaulting to: ["
+ << _DEFAULT_MEMODIR
+ << "]" << endl;
+ }
+
+ _memo_directory = dir;
+ _sync_private = MemofileConduitSettings::syncPrivate();
+
+
+ DEBUGKPILOT << fname
+ << ": Settings... "
+ << " directory: [" << _memo_directory
+ << "], first sync: [" << isFirstSync()
+ << "], sync private: [" << _sync_private
+ << "]" << endl;
+
+ return true;
+
+}
+
+bool MemofileConduit::setAppInfo()
+{
+ FUNCTIONSETUP;
+
+ // reset our category mapping from the filesystem
+ MemoCategoryMap map = _memofiles->readCategoryMetadata();
+
+ if (map.count() <=0) {
+ DEBUGKPILOT << fname
+ << ": category metadata map is empty, nothing to do." << endl;
+ return true;
+ }
+
+ fCategories = map;
+
+ for (unsigned int i = 0; i < Pilot::CATEGORY_COUNT; i++)
+ {
+ if (fCategories.contains(i)) {
+ fMemoAppInfo->setCategoryName(i,fCategories[i]);
+ }
+ }
+
+ if (fDatabase)
+ {
+ fMemoAppInfo->writeTo(fDatabase);
+ }
+ if (fLocalDatabase)
+ {
+ fMemoAppInfo->writeTo(fLocalDatabase);
+ }
+
+ return true;
+}
+
+bool MemofileConduit::getAppInfo()
+{
+ FUNCTIONSETUP;
+
+ KPILOT_DELETE(fMemoAppInfo);
+ fMemoAppInfo = new PilotMemoInfo(fDatabase);
+ fMemoAppInfo->dump();
+ return true;
+}
+
+
+/**
+ * Methods related to getting set up from the Pilot.
+ */
+
+bool MemofileConduit::initializeFromPilot()
+{
+
+ if (!getAppInfo()) return false;
+
+ if (!loadPilotCategories()) return false;
+
+ return true;
+}
+
+bool MemofileConduit::loadPilotCategories()
+{
+ FUNCTIONSETUP;
+
+ fCategories.clear();
+
+ QString _category_name;
+ int _category_id=0;
+ int _category_num=0;
+
+ for (unsigned int i = 0; i < Pilot::CATEGORY_COUNT; i++)
+ {
+ _category_name = fMemoAppInfo->categoryName(i);
+ if (!_category_name.isEmpty())
+ {
+ _category_name = Memofiles::sanitizeName( _category_name );
+ _category_id = fMemoAppInfo->categoryInfo()->ID[i];
+ _category_num = i;
+ fCategories[_category_num] = _category_name;
+
+ DEBUGKPILOT << fname
+ << ": Category #"
+ << _category_num
+ << " has ID "
+ << _category_id
+ << " and name "
+ <<_category_name << endl;
+ }
+ }
+ return true;
+}
+
+/**
+ * Read all memos in from Pilot.
+ */
+void MemofileConduit::getAllFromPilot()
+{
+ FUNCTIONSETUP;
+
+ DEBUGKPILOT << fname
+ << ": Database has " << fDatabase->recordCount()
+ << " records." << endl;
+
+ fMemoList.clear();
+
+ int currentRecord = 0;
+ PilotRecord *pilotRec;
+ PilotMemo *memo = 0;
+
+ while ((pilotRec = fDatabase->readRecordByIndex(currentRecord)) != NULL) {
+ if ((!pilotRec->isSecret()) || _sync_private) {
+ memo = new PilotMemo(pilotRec);
+ fMemoList.append(memo);
+
+ DEBUGKPILOT << fname
+ << ": Added memo: ["
+ << currentRecord
+ << "], id: ["
+ << memo->id()
+ << "], category: ["
+ << fCategories[memo->category()]
+ << "], title: ["
+ << memo->getTitle()
+ << "]" << endl;
+ } else {
+ DEBUGKPILOT << fname
+ << ": Skipped secret record: ["
+ << currentRecord
+ << "], title: ["
+ << memo->getTitle()
+ << "]" << endl;
+ }
+
+ KPILOT_DELETE(pilotRec);
+
+ currentRecord++;
+ }
+
+ DEBUGKPILOT << fname
+ << ": read: [" << fMemoList.count()
+ << "] records from palm." << endl;
+}
+
+/**
+ * Read all modified memos in from Pilot.
+ */
+void MemofileConduit::getModifiedFromPilot()
+{
+ FUNCTIONSETUP;
+
+ fMemoList.clear();
+
+ int currentRecord = 0;
+ PilotRecord *pilotRec;
+ PilotMemo *memo = 0;
+
+ while ((pilotRec = fDatabase->readNextModifiedRec()) != NULL) {
+ memo = new PilotMemo(pilotRec);
+ // we are syncing to both our filesystem and to the local
+ // database, so take care of the local database here
+ if (memo->isDeleted()) {
+ fLocalDatabase->deleteRecord(memo->id());
+ } else {
+ fLocalDatabase->writeRecord(pilotRec);
+ }
+
+ if ((!pilotRec->isSecret()) || _sync_private) {
+ fMemoList.append(memo);
+
+ DEBUGKPILOT << fname
+ << ": modified memo id: ["
+ << memo->id()
+ << "], title: ["
+ << memo->getTitle()
+ << "]" << endl;
+ } else {
+ DEBUGKPILOT << fname
+ << ": skipped secret modified record id: ["
+ << memo->id()
+ << "], title: ["
+ << memo->getTitle()
+ << "]" << endl;
+ }
+
+ KPILOT_DELETE(pilotRec);
+
+ currentRecord++;
+ }
+
+ DEBUGKPILOT << fname
+ << ": read: [" << fMemoList.count()
+ << "] modified records from palm." << endl;
+}
+
+
+/* slot */ void MemofileConduit::process()
+{
+ FUNCTIONSETUP;
+
+ DEBUGKPILOT << fname << ": Now in state " << fActionStatus << endl;
+}
+
+
+void MemofileConduit::listPilotMemos()
+{
+ FUNCTIONSETUP;
+
+ PilotMemo *memo;
+ for ( memo = fMemoList.first(); memo; memo = fMemoList.next() ) {
+ QString _category_name = fCategories[memo->category()];
+
+ DEBUGKPILOT << fConduitName
+ << ": listing record id: [" << memo->id()
+ << "] category id: [" << memo->category()
+ << "] category name: [" << _category_name
+ << "] title: [" << memo->getTitle()
+ << "]" << endl;
+ }
+}
+
+bool MemofileConduit::copyHHToPC()
+{
+ FUNCTIONSETUP;
+
+ getAllFromPilot();
+
+ _memofiles->eraseLocalMemos();
+
+ _memofiles->setPilotMemos(fMemoList);
+
+ _memofiles->save();
+
+ return true;
+
+}
+
+bool MemofileConduit::copyPCToHH()
+{
+ FUNCTIONSETUP;
+
+ // set category info from the filesystem, if we can.
+ // Note: This will reset both fCategories and fMemoAppInfo, so
+ // after this, we need to reinitialize our memofiles object...
+ setAppInfo();
+
+ // re-create our memofiles helper...
+ KPILOT_DELETE(_memofiles);
+ _memofiles = new Memofiles(fCategories, *fMemoAppInfo,
+ _memo_directory, *fCtrHH);
+
+ _memofiles->load(true);
+
+ QPtrList<Memofile> memofiles = _memofiles->getAll();
+
+ Memofile * memofile;
+
+ for ( memofile = memofiles.first(); memofile; memofile = memofiles.next() ) {
+ writeToPilot(memofile);
+ }
+
+ _memofiles->save();
+
+ // now that we've copied from the PC to our handheld, remove anything extra from the
+ // handheld...
+ deleteUnsyncedHHRecords();
+
+ return true;
+
+}
+
+void MemofileConduit::deleteUnsyncedHHRecords()
+{
+ FUNCTIONSETUP;
+ if ( syncMode()==SyncMode::eCopyPCToHH )
+ {
+ Pilot::RecordIDList ids=fDatabase->idList();
+ Pilot::RecordIDList::iterator it;
+ for ( it = ids.begin(); it != ids.end(); ++it )
+ {
+ if (!_memofiles->find(*it))
+ {
+ DEBUGKPILOT << fname
+ << "Deleting record with ID "<< *it <<" from handheld "
+ << "(is not on PC, and syncing with PC->HH direction)"
+ << endl;
+ fDatabase->deleteRecord(*it);
+ fLocalDatabase->deleteRecord(*it);
+ }
+ }
+ }
+}
+
+int MemofileConduit::writeToPilot(Memofile * memofile)
+{
+ FUNCTIONSETUP;
+
+ int oldid = memofile->id();
+
+ PilotRecord *r = memofile->pack();
+
+ if (!r) {
+ DEBUGKPILOT << fname
+ << ": ERROR: [" << memofile->toString()
+ << "] could not be written to the pilot."
+ << endl;
+ return -1;
+ }
+
+ int newid = fDatabase->writeRecord(r);
+ fLocalDatabase->writeRecord(r);
+
+ KPILOT_DELETE(r);
+
+ memofile->setID(newid);
+
+ QString status;
+ if (oldid <=0) {
+ fCtrHH->created();
+ status = "new to pilot";
+ } else {
+ fCtrHH->updated();
+ status = "updated";
+ }
+
+ DEBUGKPILOT << fname
+ << ": memofile: [" << memofile->toString()
+ << "] written to the pilot, [" << status << "]."
+ << endl;
+
+ return newid;
+}
+
+void MemofileConduit::deleteFromPilot(PilotMemo * memo)
+{
+ FUNCTIONSETUP;
+
+ PilotRecord *r = memo->pack();
+ if (r) {
+ r->setDeleted(true);
+ fDatabase->writeRecord(r);
+ fLocalDatabase->writeRecord(r);
+ }
+ KPILOT_DELETE(r);
+
+ fCtrHH->deleted();
+
+ DEBUGKPILOT << fname
+ << ": memo: [" << memo->getTitle()
+ << "] deleted from the pilot."
+ << endl;
+}
+
+bool MemofileConduit::sync()
+{
+ FUNCTIONSETUP;
+
+ _memofiles->load(false);
+
+ getModifiedFromPilot();
+
+ PilotMemo *memo;
+ for ( memo = fMemoList.first(); memo; memo = fMemoList.next() ) {
+ _memofiles->addModifiedMemo(memo);
+ }
+
+ QPtrList<Memofile> memofiles = _memofiles->getModified();
+
+ Memofile *memofile;
+ for ( memofile = memofiles.first(); memofile; memofile = memofiles.next() ) {
+ if (memofile->isDeleted()) {
+ deleteFromPilot(memofile);
+ } else {
+ writeToPilot(memofile);
+ }
+ }
+
+ _memofiles->save();
+
+ return true;
+}
+
+void MemofileConduit::cleanup()
+{
+ FUNCTIONSETUP;
+
+ fDatabase->resetSyncFlags();
+ fDatabase->cleanup();
+ fLocalDatabase->resetSyncFlags();
+ fLocalDatabase->cleanup();
+
+ fCtrPC->setEndCount(_memofiles->count());
+}
+
+
+#include "memofile-conduit.moc"
+
diff --git a/kpilot/conduits/memofileconduit/memofile-conduit.desktop b/kpilot/conduits/memofileconduit/memofile-conduit.desktop
new file mode 100644
index 000000000..c453821f5
--- /dev/null
+++ b/kpilot/conduits/memofileconduit/memofile-conduit.desktop
@@ -0,0 +1,93 @@
+[Desktop Entry]
+Type=Service
+Name=Memo File
+Name[af]=Memo Lêer
+Name[bg]=Бележка
+Name[ca]=Fitxer de notes
+Name[cs]=Soubor s poznámkou
+Name[da]=Memo-fil
+Name[de]=Memo Datei
+Name[el]=ΑÏχείο υπομνήματος
+Name[eo]=Memo-dosiero
+Name[es]=Archivo de nota
+Name[et]=Memofail
+Name[eu]=Ohar fitxategia
+Name[fa]=پروندۀ Memo
+Name[fi]=Muistiotiedosto
+Name[fr]=Fichier mémo
+Name[fy]=Memotriem
+Name[ga]=Comhad Meamraim
+Name[gl]=Ficheiro Memo
+Name[hu]=Memófájl
+Name[is]=Minnismiðaskrá
+Name[it]=File appunti
+Name[ja]=メモファイル
+Name[ka]=ჩáƒáƒœáƒ˜áƒ¨áƒ•áƒœáƒ
+Name[kk]=Жазба файлы
+Name[km]=ឯកសារ​អនុស្សរណៈ
+Name[lt]=Memo byla
+Name[ms]=Fail Memo
+Name[nb]=Notatfil
+Name[nds]=Notiz-Datei
+Name[ne]=सà¥à¤®à¥ƒà¤¤à¤¿ फाइल
+Name[nl]=Memobestand
+Name[nn]=Memofil
+Name[pl]=Plik notatki
+Name[pt]=Ficheiro Memorando
+Name[pt_BR]=Arquivo Memo
+Name[ru]=Заметка
+Name[sk]=Memo súbor
+Name[sl]=Datoteka z opombami
+Name[sv]=Anteckningsfil
+Name[ta]=மெமோ கோபà¯à®ªà¯
+Name[tr]=Hatırlatma Dosyası
+Name[uk]=Файл примітки
+Name[zh_CN]=备忘文件
+Name[zh_TW]=Memo 檔
+Comment=This conduit syncs your handheld memos with a local directory.
+Comment[af]=Hierdie pad sinkroniseer jou draagbare toestel se memos met 'n plaaslike gids.
+Comment[bg]=Ð¡Ð¸Ð½Ñ…Ñ€Ð¾Ð½Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð½Ð° бележките на KDE Ñ Ð¼Ð¾Ð±Ð¸Ð»Ð½Ð¸ уÑтройÑтва.
+Comment[ca]=Aquest conducte sincronitza les notes de l'agenda electrònica amb un directori local.
+Comment[cs]=Toto propojení synchronizuje vaše poznámky v PDA s lokálním adresářem.
+Comment[da]=Denne kanal synkroniserer dine håndholdte memoer med en lokal mappe.
+Comment[de]=Abgleich der Memos von Taschencomputer und einem lokalen Ordner
+Comment[el]=Αυτός ο σÏνδεσμος συγχÏονίζει τα υπομνήματα του υπολογιστή παλάμης σας με έναν τοπικό κατάλογο.
+Comment[eo]=Tiu kanalo sinkronigas viajn poÅkomputil-memoojn kun loka dosierujo.
+Comment[es]=Este conducto sincroniza las notas de su agenda electrónica con el directorio local.
+Comment[et]=See kanal sünkroniseerib pihuarvutis ja arvutis olevad memod.
+Comment[eu]=Kanal honek zure agendako oharrak direktorio lokal batekin sinkronizatzen ditu.
+Comment[fa]=این لوله، memo‌های دستی خود را با Ùهرست راهنمای محلی همگام‌سازی می‌کند.
+Comment[fi]=Tämä yhdyskäytävä synkronoi taskutietokoneen muistiot paikalliseen kansioon.
+Comment[fr]=Ce canal synchronise les mémos du Palm avec ceux de KDE.
+Comment[fy]=Dit conduit syngronisearret de memo's fan jo handheld mei in lokale triemtafel.
+Comment[gl]=Este conducto sincroniza os memos do seu aparello portátil cun cartafol local.
+Comment[hu]=Ezzel a csatolóval egy kézi számítógép memóit lehet szinkronizálni a helyi címjegyzékkel.
+Comment[is]=Þessi rás samstillir minnismiða lófatölvunnar þinnar við staðbundna möppu.
+Comment[it]=Questo condotto sincronizza gli appunti del tuo palmare con una cartella locale.
+Comment[ja]=ã“ã®ã‚³ãƒ³ã‚¸ãƒƒãƒˆã¯ãƒãƒ³ãƒ‰ãƒ˜ãƒ«ãƒ‰ã®ãƒ¡ãƒ¢ã‚’ローカルã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã¨åŒæœŸã•ã›ã¾ã™ã€‚
+Comment[ka]=ეს áƒáƒ áƒ®áƒ˜ თქვენი პáƒáƒ áƒ¢áƒáƒ¢áƒ˜áƒ£áƒšáƒ˜ მáƒáƒ¬áƒ§áƒáƒ‘ილáƒáƒ‘ის ლáƒáƒ™áƒáƒšáƒ£áƒ  დირექტáƒáƒ áƒ˜áƒáƒ¡áƒ—áƒáƒœ სინქრáƒáƒœáƒ˜áƒ–áƒáƒªáƒ˜áƒáƒ¡ áƒáƒ®áƒ“ენს .
+Comment[kk]=Қалта құрылғыдағы жазбаларды қапшықтағы файлымен қадамдаÑтыру арнаÑÑ‹.
+Comment[km]=បំពង់​នáŸáŸ‡â€‹áž¢áž¶áž…​ឲ្យ​អនុស្សរណៈ​ឧបករណáŸâ€‹áž™áž½ážšâ€‹ážŠáŸƒâ€‹ážšáž”ស់​អ្នក ធ្វើ​សមកាលកម្ម​ជាមួយ​នឹង​ážážâ€‹áž˜áž¼áž›ážŠáŸ’ឋាន ។​
+Comment[lt]=Šis kanalas sinchronizuoja Jūsų užrašus su vietiniu aplanku.
+Comment[ms]=Saluran ini mensegerakkan memo komputer telapak anda dengan direktori setempat.
+Comment[nb]=Denne kanalen synkroniserer PDA-ens notater med en lokal mappe.
+Comment[nds]=Synkroniseert de Notizen op den Handreekner mit en lokaal Orner.
+Comment[ne]=यो कनà¥à¤¡à¥à¤¯à¥à¤Ÿà¤²à¥‡ सà¥à¤¥à¤¾à¤¨à¥€à¤¯ डाइरेकà¥à¤Ÿà¤°à¥€à¤®à¤¾ तपाईà¤à¤•à¤¾ हà¥à¤¯à¤¾à¤¨à¥à¤¡à¤¹à¥‡à¤²à¥à¤¡ मेमो सिनà¥à¤• गरà¥à¤¦à¤› ।
+Comment[nl]=Dit conduit synchroniseert de memo's van uw handheld met een lokale map.
+Comment[pl]=Ten Å‚Ä…cznik synchronizuje notatki z palmtopa z lokalnym katalogiem.
+Comment[pt]=Esta conduta sincroniza os memorandos do seu PDA com uma pasta local.
+Comment[pt_BR]=Este conduíte sincroniza as anotações no seu handheld com um diretório local.
+Comment[ru]=Канал Ñинхронизации заметок КПК и KDE.
+Comment[sk]=Táto spojka synchronizuje adresár vášho prenosného zariadenia s lokálnym prieÄinkom.
+Comment[sl]=Ta veznik usklajuje opombe v roÄnem raÄunalniku s krajevnim imenikom.
+Comment[sr]=Овај провод Ñинхронизује белешке на вашем ручном рачунару Ñа локалним директоријумом.
+Comment[sr@Latn]=Ovaj provod sinhronizuje beleÅ¡ke na vaÅ¡em ruÄnom raÄunaru sa lokalnim direktorijumom.
+Comment[sv]=Den här kanalen synkroniserar handdatorns anteckningar med en lokal katalog.
+Comment[ta]=இநà¯à®¤ கà¯à®´à®¾à®¯à¯ கையில௠உளà¯à®³ à®®à¯à®•à®µà®°à®¿à®ªà¯à®ªà¯à®¤à¯à®¤à®•à®¤à¯à®¤à¯ˆ கேடிஇயின௠மà¯à®•à®µà®°à®¿à®ªà¯à®ªà¯à®¤à¯à®¤à®•à®¤à¯à®¤à¯‹à®Ÿà¯ ஒதà¯à®¤à®¿à®šà¯ˆà®•à¯à®•à®¿à®±à®¤à¯
+Comment[tr]=Bu bileşen el bilgisayarı hatırlatmalarını yerel bir dosyaya aktarır veya alır.
+Comment[uk]=Цей акведук Ñинхронізує примітки кишенькового приÑтрою з локальним каталогом.
+Comment[zh_CN]=此管é“会将您手æŒè®¾å¤‡ä¸­çš„备忘与本地目录åŒæ­¥ã€‚
+Comment[zh_TW]=此軟體åŒæ­¥æ‚¨çš„ handheld memo åŠæœ¬åœ°ç«¯ç›®éŒ„。
+Implemented=file
+ServiceTypes=KPilotConduit
+X-KDE-Library=conduit_memofile
diff --git a/kpilot/conduits/memofileconduit/memofile-conduit.h b/kpilot/conduits/memofileconduit/memofile-conduit.h
new file mode 100644
index 000000000..08fdbd0f7
--- /dev/null
+++ b/kpilot/conduits/memofileconduit/memofile-conduit.h
@@ -0,0 +1,92 @@
+#ifndef _MEMOFILE_MEMOFILE_CONDUIT_H
+#define _MEMOFILE_MEMOFILE_CONDUIT_H
+/* memofile-conduit.h KPilot
+**
+** Copyright (C) 2004-2007 by Jason 'vanRijn' Kasper
+*/
+
+/*
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU Lesser General Public License as published by
+** the Free Software Foundation; either version 2.1 of the License, or
+** (at your option) any later version.
+**
+** This 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 Lesser General Public License for more details.
+**
+** You should have received a copy of the GNU Lesser General Public License
+** along with this program in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include <pi-memo.h>
+
+#include "plugin.h"
+
+#include "memofiles.h"
+
+class PilotMemo;
+
+class MemofileConduit : public ConduitAction
+{
+Q_OBJECT
+public:
+ MemofileConduit(KPilotLink *,
+ const char *name=0L,
+ const QStringList &args = QStringList());
+ virtual ~MemofileConduit();
+
+protected:
+ virtual bool exec();
+
+
+protected slots:
+ void process();
+
+private:
+ // configuration settings...
+ QString _DEFAULT_MEMODIR;
+ QString _memo_directory;
+ bool _sync_private;
+
+ PilotMemoInfo *fMemoAppInfo;
+ QPtrList<PilotMemo> fMemoList;
+
+ // our categories
+ MemoCategoryMap fCategories;
+
+ Memofiles * _memofiles;
+
+
+ bool readConfig();
+ bool getAppInfo();
+ bool setAppInfo();
+
+ bool initializeFromPilot();
+ bool loadPilotCategories();
+
+ void listPilotMemos();
+
+ void getAllFromPilot();
+ void getModifiedFromPilot();
+
+ bool copyHHToPC();
+ bool copyPCToHH();
+ void deleteUnsyncedHHRecords();
+ bool sync();
+
+ int writeToPilot(Memofile * memofile);
+ void deleteFromPilot(PilotMemo* memo);
+
+ void cleanup();
+
+};
+
+#endif
diff --git a/kpilot/conduits/memofileconduit/memofile-factory.cc b/kpilot/conduits/memofileconduit/memofile-factory.cc
new file mode 100644
index 000000000..e373a0185
--- /dev/null
+++ b/kpilot/conduits/memofileconduit/memofile-factory.cc
@@ -0,0 +1,128 @@
+/* memofile-factory.cc KPilot
+**
+** Copyright (C) 2004-2007 by Jason 'vanRijn' Kasper
+**
+** This file defines the factory for the memofile-conduit plugin.
+*/
+
+/*
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU Lesser General Public License as published by
+** the Free Software Foundation; either version 2.1 of the License, or
+** (at your option) any later version.
+**
+** This 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 Lesser General Public License for more details.
+**
+** You should have received a copy of the GNU Lesser General Public License
+** along with this program in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include "options.h"
+
+#include <qtabwidget.h>
+#include <qlineedit.h>
+#include <qcheckbox.h>
+
+#include <kconfig.h>
+#include <kinstance.h>
+#include <kaboutdata.h>
+#include <kurlrequester.h>
+
+#include "setup_base.h"
+#include "memofile-conduit.h"
+#include "memofileSettings.h"
+
+#include "pluginfactory.h"
+
+class MemofileConduitConfig : public ConduitConfigBase
+{
+public:
+ MemofileConduitConfig(QWidget *parent=0L, const char *n=0L);
+ virtual void commit();
+ virtual void load();
+protected:
+ MemofileWidget *fConfigWidget;
+} ;
+
+MemofileConduitConfig::MemofileConduitConfig(QWidget *p, const char *n) :
+ ConduitConfigBase(p,n),
+ fConfigWidget(new MemofileWidget(p))
+{
+ FUNCTIONSETUP;
+ fConduitName = i18n("Memofile");
+ KAboutData *about = new KAboutData("MemofileConduit",
+ I18N_NOOP("Memofile Conduit for KPilot"),
+ KPILOT_VERSION,
+ I18N_NOOP("Configures the Memofile Conduit for KPilot"),
+ KAboutData::License_GPL,
+ "(C) 2004, Jason 'vanRijn' Kasper");
+ about->addAuthor("Jason 'vanRijn' Kasper",
+ I18N_NOOP("Primary Author"),
+ "vR@movingparts.net",
+ "http://www.cs.kun.nl/~adridg/kpilot");
+
+ ConduitConfigBase::addAboutPage(fConfigWidget->tabWidget,about);
+ fWidget=fConfigWidget;
+ QObject::connect(fConfigWidget->fDirectory,SIGNAL(textChanged(const QString&)),
+ this,SLOT(modified()));
+ QObject::connect(fConfigWidget->fSyncPrivate,SIGNAL(toggled(bool)),
+ this,SLOT(modified()));
+
+}
+
+/* virtual */ void MemofileConduitConfig::commit()
+{
+ FUNCTIONSETUP;
+
+ DEBUGKPILOT << fname
+ << ": Directory="
+ << fConfigWidget->fDirectory->url()
+ << endl;
+
+ MemofileConduitSettings::setDirectory( fConfigWidget->fDirectory->url() );
+ MemofileConduitSettings::setSyncPrivate( fConfigWidget->fSyncPrivate->isChecked() );
+ MemofileConduitSettings::self()->writeConfig();
+ unmodified();
+}
+
+/* virtual */ void MemofileConduitConfig::load()
+{
+ FUNCTIONSETUP;
+ MemofileConduitSettings::self()->readConfig();
+
+ fConfigWidget->fDirectory->setURL( MemofileConduitSettings::directory() );
+ fConfigWidget->fSyncPrivate->setChecked( MemofileConduitSettings::syncPrivate() );
+
+ DEBUGKPILOT << fname
+ << ": Read Directory: ["
+ << fConfigWidget->fDirectory->url()
+ << "], sync private records: ["
+ << fConfigWidget->fSyncPrivate
+ << "]" << endl;
+
+ unmodified();
+}
+
+
+
+extern "C"
+{
+
+void *init_conduit_memofile()
+{
+ return new ConduitFactory<MemofileConduitConfig,MemofileConduit>(0,"memofileconduit");
+}
+
+unsigned long version_conduit_memofile = Pilot::PLUGIN_API;
+
+}
+
diff --git a/kpilot/conduits/memofileconduit/memofile-factory.h b/kpilot/conduits/memofileconduit/memofile-factory.h
new file mode 100644
index 000000000..b42fb6577
--- /dev/null
+++ b/kpilot/conduits/memofileconduit/memofile-factory.h
@@ -0,0 +1,40 @@
+#ifndef _KPILOT_MEMOFILE_FACTORY_H
+#define _KPILOT_MEMOFILE_FACTORY_H
+/* memofile-factory.h KPilot
+**
+** Copyright (C) 2004-2007 by Jason 'vanRijn' Kasper
+**
+** This file defines the factory for the Memofile-conduit plugin.
+** It also defines the class for the behavior of the setup dialog.
+*/
+
+/*
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU Lesser General Public License as published by
+** the Free Software Foundation; either version 2.1 of the License, or
+** (at your option) any later version.
+**
+** This 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 Lesser General Public License for more details.
+**
+** You should have received a copy of the GNU Lesser General Public License
+** along with this program in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+
+extern "C"
+{
+
+void *init_libmemofileconduit();
+
+}
+
+#endif
diff --git a/kpilot/conduits/memofileconduit/memofile.cc b/kpilot/conduits/memofileconduit/memofile.cc
new file mode 100644
index 000000000..1428c487d
--- /dev/null
+++ b/kpilot/conduits/memofileconduit/memofile.cc
@@ -0,0 +1,239 @@
+/* memofile.cc KPilot
+**
+** Copyright (C) 2004-2007 by Jason 'vanRijn' Kasper
+**
+*/
+
+/*
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU Lesser General Public License as published by
+** the Free Software Foundation; either version 2.1 of the License, or
+** (at your option) any later version.
+**
+** This 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 Lesser General Public License for more details.
+**
+** You should have received a copy of the GNU Lesser General Public License
+** along with this program in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include "memofile.h"
+
+Memofile::Memofile(PilotMemo * memo, QString categoryName, QString fileName, QString baseDirectory) :
+ PilotMemo(memo,memo->text()), _categoryName(categoryName), _filename(fileName), _baseDirectory(baseDirectory)
+{
+ _lastModified = 0;
+ _size = 0;
+ _modified = _modifiedByPalm = false;
+}
+
+Memofile::Memofile(recordid_t id, int category, uint lastModifiedTime, uint size,
+ QString categoryName, QString fileName, QString baseDirectory) :
+ PilotMemo(), _categoryName(categoryName),
+ _filename(fileName),_baseDirectory(baseDirectory)
+{
+ setID(id);
+ PilotRecordBase::setCategory(category);
+ _lastModified = lastModifiedTime;
+ _size = size;
+ _modified = _modifiedByPalm = false;
+}
+
+Memofile::Memofile(int category, QString categoryName, QString fileName, QString baseDirectory) :
+ PilotMemo(),
+ _categoryName(categoryName), _filename(fileName), _baseDirectory(baseDirectory)
+{
+ setID(0);
+ _new = true;
+ PilotRecordBase::setCategory(category);
+ _modified = true;
+ _modifiedByPalm = false;
+ _lastModified = 0;
+ _size = 0;
+}
+
+bool Memofile::load()
+{
+ FUNCTIONSETUP;
+ if (filename().isEmpty()) {
+ DEBUGKPILOT << fname
+ << ": I was asked to load, but have no filename to load. "
+ << endl;
+ return false;
+ }
+
+ QFile f( filenameAbs() );
+ if ( !f.open( IO_ReadOnly ) ) {
+ DEBUGKPILOT << fname
+ << ": Couldn't open file: [" << filenameAbs() << "] to read. "
+ << endl;
+ return false;
+ }
+
+ QTextStream ts( &f );
+
+ QString text,title,body;
+ title = filename();
+ body = ts.read();
+
+ // funky magic. we want the text of the memofile to have the filename
+ // as the first line....
+ if (body.startsWith(title)) {
+ text = body;
+ } else {
+ DEBUGKPILOT << fname
+ << ": text of your memofile: [" << filename()
+ << "] didn't include the filename as the first line. fixing it..." << endl;
+ text = title + CSL1("\n") + body;
+ }
+
+ // check length of text. if it's over the allowable length, warn user.
+ // NOTE: We don't need to truncate this here, since PilotMemo::setText()
+ // does it for us.
+ int _len = text.length();
+ int _maxlen = PilotMemo::MAX_MEMO_LEN;
+ if (_len > _maxlen) {
+ DEBUGKPILOT << fname << ": memofile: [" << filename()
+ << "] length: [" << _len << "] is over maximum: ["
+ << _maxlen << "] and will be truncated to fit." << endl;
+ }
+
+ setText(text);
+ f.close();
+
+ return true;
+}
+
+void Memofile::setID(recordid_t i)
+{
+ if (i != id())
+ _modifiedByPalm = true;
+
+ PilotMemo::setID(i);
+}
+
+bool Memofile::save()
+{
+ bool result = true;
+
+ if ((isModified() && isLoaded()) || _modifiedByPalm) {
+ result = saveFile();
+ }
+
+ return result;
+}
+
+bool Memofile::deleteFile()
+{
+ FUNCTIONSETUP;
+ DEBUGKPILOT << fname
+ << ": deleting file: [" << filenameAbs() << "]." << endl;
+ return QFile::remove(filenameAbs());
+
+}
+
+bool Memofile::saveFile()
+{
+ FUNCTIONSETUP;
+
+ if (filename().isEmpty()) {
+ DEBUGKPILOT << fname
+ << ": I was asked to save, but have no filename to save to. "
+ << endl;
+ return false;
+ }
+
+ DEBUGKPILOT << fname
+ << ": saving memo to file: ["
+ << filenameAbs() << "]" << endl;
+
+
+ QFile f( filenameAbs() );
+ if ( !f.open( IO_WriteOnly ) ) {
+ DEBUGKPILOT << fname
+ << ": Couldn't open file: [" << filenameAbs() << "] to write your memo to. "
+ << "This won't end well." << endl;
+ return false;
+ }
+
+ QTextStream stream(&f);
+ stream << text() << endl;
+ f.close();
+
+ _lastModified = getFileLastModified();
+ _size = getFileSize();
+
+ return true;
+
+}
+
+bool Memofile::isModified(void)
+{
+ // first, check to see if this file is deleted....
+ if (!fileExists()) {
+ return true;
+ }
+
+ bool modByTimestamp = false;
+ bool modBySize = false;
+
+ if (_lastModified > 0)
+ modByTimestamp = isModifiedByTimestamp();
+
+ if (_size > 0)
+ modBySize = isModifiedBySize();
+
+ bool ret = _modified || modByTimestamp || modBySize;
+
+ return ret;
+}
+
+bool Memofile::isModifiedByTimestamp()
+{
+ if (_lastModified <=0) {
+ return true;
+ }
+
+ uint lastModifiedTime = getFileLastModified();
+ if ( lastModifiedTime != _lastModified) {
+ return true;
+ }
+
+ return false;
+}
+
+bool Memofile::isModifiedBySize()
+{
+ if (_size <=0) {
+ return true;
+ }
+
+ uint size = getFileSize();
+ if ( size != _size) {
+ return true;
+ }
+
+ return false;
+}
+
+uint Memofile::getFileLastModified()
+{
+ QFileInfo f = QFileInfo(filenameAbs());
+ uint lastModifiedTime = f.lastModified().toTime_t();
+ return lastModifiedTime;
+}
+
+uint Memofile::getFileSize()
+{
+ QFileInfo f = QFileInfo(filenameAbs());
+ uint size = f.size();
+ return size;
+}
diff --git a/kpilot/conduits/memofileconduit/memofile.h b/kpilot/conduits/memofileconduit/memofile.h
new file mode 100644
index 000000000..27931cdfe
--- /dev/null
+++ b/kpilot/conduits/memofileconduit/memofile.h
@@ -0,0 +1,113 @@
+#ifndef _MEMOFILE_MEMOFILE_H
+#define _MEMOFILE_MEMOFILE_H
+/* memofile.h KPilot
+**
+** Copyright (C) 2004-2007 by Jason 'vanRijn' Kasper
+**
+*/
+
+/*
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU Lesser General Public License as published by
+** the Free Software Foundation; either version 2.1 of the License, or
+** (at your option) any later version.
+**
+** This 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 Lesser General Public License for more details.
+**
+** You should have received a copy of the GNU Lesser General Public License
+** along with this program in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+
+#include "options.h"
+
+// Only include what we really need:
+// First UNIX system stuff, then std C++,
+// then Qt, then KDE, then local includes.
+//
+//
+
+#include <time.h> // required by pilot-link includes
+
+#include <pi-memo.h>
+
+#include <qfile.h>
+#include <qdir.h>
+#include <qtextstream.h>
+#include <qtextcodec.h>
+
+#include "pilotMemo.h"
+
+#include "memofiles.h"
+
+/**
+ * Class that represents our filesystem memo.
+ */
+class Memofile : public PilotMemo
+{
+ public:
+ Memofile(PilotMemo * memo, QString categoryName, QString fileName, QString baseDirectory);
+ Memofile(recordid_t id, int category, uint lastModifiedTime, uint size, QString categoryName, QString filename, QString baseDirectory);
+ Memofile(int category, QString categoryName, QString fileName, QString baseDirectory);
+
+ uint lastModified() const { return _lastModified; } ;
+ uint size() const { return _size; } ;
+
+ void setModifiedByPalm(bool mod) { _modifiedByPalm = mod; } ;
+ void setModified(bool modified) { _modified = modified; } ;
+
+ bool isModified(void);
+ bool isModifiedByPalm() { return _modifiedByPalm; } ;
+ bool isLoaded(void) { return (! text().isEmpty()); } ;
+ bool isNew(void) { return _new; } ;
+
+ bool load();
+
+ bool fileExists() { return QFile::exists(filenameAbs()); } ;
+
+ void setID(recordid_t id);
+
+ bool save();
+ bool deleteFile();
+
+ QString toString() {
+ return CSL1("id: [") + QString::number(id())
+ + CSL1("], category:[") + _categoryName
+ + CSL1("], filename: [") + _filename + CSL1("]");
+ } ;
+ const QString & getCategoryName() { return _categoryName; } ;
+ const QString & getFilename() { return _filename; } ;
+ const QString & filename() { return _filename; } ;
+
+ private:
+ bool saveFile();
+ bool isModifiedByTimestamp();
+ bool isModifiedBySize();
+
+ QString filenameAbs() { return dirName() + filename(); } ;
+ QString dirName() { return _baseDirectory + QDir::separator() + _categoryName + QDir::separator(); } ;
+ bool setCategory(const QString &label);
+ uint getFileLastModified();
+ uint getFileSize();
+
+ bool _modifiedByPalm;
+ bool _modified;
+ bool _new;
+ uint _lastModified;
+ uint _size;
+
+ QString _categoryName;
+ QString _filename;
+ QString _baseDirectory;
+} ;
+
+#endif
diff --git a/kpilot/conduits/memofileconduit/memofileSettings.kcfgc b/kpilot/conduits/memofileconduit/memofileSettings.kcfgc
new file mode 100644
index 000000000..3d1373b88
--- /dev/null
+++ b/kpilot/conduits/memofileconduit/memofileSettings.kcfgc
@@ -0,0 +1,7 @@
+File=memofileconduit.kcfg
+ClassName= MemofileConduitSettings
+Singleton=true
+ItemAccessors=true
+Mutators=true
+GlobalEnums=true
+SetUserTexts=true
diff --git a/kpilot/conduits/memofileconduit/memofileconduit.kcfg b/kpilot/conduits/memofileconduit/memofileconduit.kcfg
new file mode 100644
index 000000000..506e040ed
--- /dev/null
+++ b/kpilot/conduits/memofileconduit/memofileconduit.kcfg
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE kcfg SYSTEM "http://www.kde.org/standards/kcfg/1.0/kcfg.dtd">
+<kcfg><kcfgfile name="kpilotrc"/>
+ <group name="memofile-conduit">
+ <entry name="Directory" type="Path">
+ <label>What directory do you want to sync your PDA's memos with?</label>
+ <default>$HOME/MyMemos</default>
+ </entry>
+ <entry name="SyncPrivate" type="Bool">
+ <label>Do you want to sync your private records to the filesystem?</label>
+ <default>true</default>
+ </entry>
+
+ </group>
+
+</kcfg>
diff --git a/kpilot/conduits/memofileconduit/memofileconduit.xmi b/kpilot/conduits/memofileconduit/memofileconduit.xmi
new file mode 100644
index 000000000..33ff89f85
--- /dev/null
+++ b/kpilot/conduits/memofileconduit/memofileconduit.xmi
@@ -0,0 +1,241 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<XMI xmlns:UML="org.omg/standards/UML" verified="false" timestamp="" xmi.version="1.2" >
+ <XMI.header>
+ <XMI.documentation>
+ <XMI.exporter>umbrello uml modeller http://uml.sf.net</XMI.exporter>
+ <XMI.exporterVersion>1.2.90</XMI.exporterVersion>
+ <XMI.exporterEncoding>UnicodeUTF8</XMI.exporterEncoding>
+ </XMI.documentation>
+ <XMI.model xmi.name="umbrelloJSFhpc" href="/tmp/kde-gideon/umbrelloJSFhpc.tmp" />
+ <XMI.metamodel xmi.name="UML" href="UML.xml" xmi.version="1.3" />
+ </XMI.header>
+ <XMI.content>
+ <UML:Model>
+ <UML:Stereotype visibility="public" xmi.id="3" name="datatype" />
+ <UML:Stereotype visibility="public" xmi.id="18" name="enum" />
+ <UML:Stereotype visibility="public" xmi.id="35" name="typedef" />
+ <UML:DataType stereotype="3" visibility="public" xmi.id="2" name="int" />
+ <UML:DataType stereotype="3" visibility="public" xmi.id="4" name="char" />
+ <UML:DataType stereotype="3" visibility="public" xmi.id="5" name="bool" />
+ <UML:DataType stereotype="3" visibility="public" xmi.id="6" name="float" />
+ <UML:DataType stereotype="3" visibility="public" xmi.id="7" name="double" />
+ <UML:DataType stereotype="3" visibility="public" xmi.id="8" name="long" />
+ <UML:DataType stereotype="3" visibility="public" xmi.id="9" name="short" />
+ <UML:DataType stereotype="3" visibility="public" xmi.id="10" name="string" />
+ <UML:Class visibility="public" xmi.id="11" name="MemofileConduit" >
+ <UML:Operation visibility="public" xmi.id="12" type="" name="MemofileConduit" >
+ <UML:Parameter visibility="public" xmi.id="13" value="" type="KPilotDeviceLink*" />
+ <UML:Parameter visibility="public" xmi.id="14" value="" type="const char*" name="name" />
+ <UML:Parameter visibility="public" xmi.id="15" value="" type="const QStringList&amp;" name="args" />
+ </UML:Operation>
+ <UML:Operation visibility="public" xmi.id="16" type="" name="~ MemofileConduit" />
+ <UML:Operation visibility="protected" xmi.id="26" type="bool" name="exec" />
+ <UML:Operation visibility="protected" xmi.id="27" type="void" name="listPilotMemos" />
+ <UML:Operation visibility="protected" xmi.id="28" type="void" name="process" />
+ <UML:Operation visibility="private" xmi.id="43" type="bool" name="readConfig" />
+ <UML:Operation visibility="private" xmi.id="44" type="void" name="getAppInfo" />
+ <UML:Operation visibility="private" xmi.id="45" type="QString" name="getCategoryName" >
+ <UML:Parameter visibility="public" xmi.id="46" value="" type="int" name="category" />
+ </UML:Operation>
+ <UML:Operation visibility="private" xmi.id="47" type="bool" name="initializeFromPilot" />
+ <UML:Operation visibility="private" xmi.id="48" type="bool" name="loadPilotMemos" />
+ <UML:Operation visibility="private" xmi.id="49" type="bool" name="loadPilotCategories" />
+ <UML:Operation visibility="private" xmi.id="50" type="bool" name="initializeFromFilesystem" />
+ <UML:Operation visibility="private" xmi.id="51" type="bool" name="initializeMemofileList" />
+ <UML:Operation visibility="private" xmi.id="52" type="bool" name="checkDirectory" >
+ <UML:Parameter visibility="public" xmi.id="53" value="" type="QString" name="dir" />
+ </UML:Operation>
+ <UML:Operation visibility="private" xmi.id="54" type="bool" name="ensureFilesystemReady" />
+ <UML:Operation visibility="private" xmi.id="55" type="bool" name="copyHHToPC" />
+ <UML:Operation visibility="private" xmi.id="56" type="bool" name="saveCategoriesToFilesystem" />
+ <UML:Operation visibility="private" xmi.id="57" type="bool" name="saveMemoInfoToFilesystem" />
+ <UML:Operation visibility="private" xmi.id="58" type="bool" name="saveMemosToFilesystem" />
+ <UML:Operation visibility="private" xmi.id="59" type="bool" name="saveAsText" >
+ <UML:Parameter visibility="public" xmi.id="60" value="" type="const QString&amp;" name="fileName" />
+ <UML:Parameter visibility="public" xmi.id="61" value="" type="Memofile*" name="theMemo" />
+ </UML:Operation>
+ <UML:Attribute visibility="private" xmi.id="29" value="" type="QString" name="_DEFAULT_MEMODIR" />
+ <UML:Attribute visibility="private" xmi.id="30" value="" type="QString" name="_memo_directory" />
+ <UML:Attribute visibility="private" xmi.id="31" value="" type="bool" name="_sync_private" />
+ <UML:Attribute visibility="private" xmi.id="32" value="" type="QPtrList&lt; PilotMemo >" name="fMemoList" />
+ <UML:Attribute visibility="private" xmi.id="33" value="" type="struct MemoAppInfo" name="fMemoAppInfo" />
+ <UML:Attribute visibility="private" xmi.id="37" value="" type="QPtrList&lt; Memofile >" name="fMemofileList" />
+ <UML:Attribute visibility="private" xmi.id="38" value="" type="int" name="fRecordIndex" />
+ <UML:Attribute visibility="private" xmi.id="39" value="" type="QTimer*" name="fTimer" />
+ <UML:Attribute visibility="private" xmi.id="40" value="" type="int" name="fCounter" />
+ <UML:Attribute visibility="private" xmi.id="41" value="" type="int" name="fDeleteCounter" />
+ <UML:Attribute visibility="private" xmi.id="42" value="" type="int" name="fModifyCounter" />
+ <UML:Enumeration stereotype="18" visibility="public" xmi.id="17" name="Status" >
+ <UML:EnumerationLiteral visibility="public" xmi.id="19" name="Init" />
+ <UML:EnumerationLiteral visibility="public" xmi.id="20" name="ModifiedFilesToPilot" />
+ <UML:EnumerationLiteral visibility="public" xmi.id="21" name="DeleteFilesOnPilot" />
+ <UML:EnumerationLiteral visibility="public" xmi.id="22" name="NewFilesToPilot" />
+ <UML:EnumerationLiteral visibility="public" xmi.id="23" name="MemosToFiles" />
+ <UML:EnumerationLiteral visibility="public" xmi.id="24" name="Cleanup" />
+ <UML:EnumerationLiteral visibility="public" xmi.id="25" name="Done" />
+ </UML:Enumeration>
+ <UML:Class stereotype="35" visibility="public" xmi.id="34" name="MemoCategoryMap" />
+ </UML:Class>
+ <UML:Class visibility="public" xmi.id="63" name="Memofiles" >
+ <UML:Operation visibility="public" xmi.id="80" type="Memofiles" name="Memofiles" >
+ <UML:Parameter visibility="public" xmi.id="81" value="" type="QMap" name="categories" />
+ <UML:Parameter visibility="public" xmi.id="82" value="" type="QString" name="baseDirectory" />
+ </UML:Operation>
+ <UML:Operation visibility="public" xmi.id="87" type="void" name="load" >
+ <UML:Parameter visibility="public" xmi.id="88" value="" type="bool" name="loadAll" />
+ </UML:Operation>
+ <UML:Operation visibility="public" xmi.id="89" type="QPtrList&lt;Memofile>" name="getAll" />
+ <UML:Operation visibility="public" xmi.id="90" type="void" name="save" />
+ <UML:Operation visibility="public" xmi.id="91" type="void" name="eraseLocalMemos" />
+ <UML:Operation visibility="public" xmi.id="95" type="void" name="setModified" >
+ <UML:Parameter visibility="public" xmi.id="96" value="" type="QPtrList&lt;PilotMemo>" name="memos" />
+ </UML:Operation>
+ <UML:Operation visibility="private" xmi.id="97" type="void" name="ensureDirectoryReady" />
+ <UML:Operation visibility="public" xmi.id="98" type="void" name="loadIds" />
+ <UML:Operation visibility="public" xmi.id="99" type="Memofile" name="find" >
+ <UML:Parameter visibility="public" xmi.id="100" value="" type="QString" name="category" />
+ <UML:Parameter visibility="public" xmi.id="101" value="" type="QString" name="filename" />
+ </UML:Operation>
+ <UML:Operation visibility="public" xmi.id="102" type="void" name="addModified" >
+ <UML:Parameter visibility="public" xmi.id="103" value="" type="PilotMemo *" name="memo" />
+ </UML:Operation>
+ <UML:Operation visibility="public" xmi.id="104" type="QPtrList&lt;Memofile>" name="getModified" />
+ <UML:Attribute visibility="private" xmi.id="83" value="" type="QMap" name="_categories" />
+ <UML:Attribute visibility="private" xmi.id="85" value="" type="QString" name="_baseDirectory" />
+ <UML:Attribute visibility="private" xmi.id="93" value="" type="QPtrList&lt;Memofile>" name="_memofiles" />
+ </UML:Class>
+ <UML:Class visibility="public" xmi.id="64" name="Memofile" >
+ <UML:Operation visibility="public" xmi.id="65" type="" name="Memofile" >
+ <UML:Parameter visibility="public" xmi.id="66" value="" type="PilotMemo*" name="memo" />
+ <UML:Parameter visibility="public" xmi.id="67" value="" type="QString" name="categoryName" />
+ </UML:Operation>
+ <UML:Operation visibility="public" xmi.id="68" type="" name="Memofile" >
+ <UML:Parameter visibility="public" xmi.id="69" value="" type="recordid_t" name="id" />
+ <UML:Parameter visibility="public" xmi.id="70" value="" type="int" name="category" />
+ <UML:Parameter visibility="public" xmi.id="71" value="" type="QString" name="categoryName" />
+ <UML:Parameter visibility="public" xmi.id="72" value="" type="uint" name="lastModifiedTime" />
+ <UML:Parameter visibility="public" xmi.id="73" value="" type="QString" name="filename" />
+ <UML:Parameter visibility="public" xmi.id="74" value="" type="QString" name="text" />
+ </UML:Operation>
+ <UML:Operation visibility="public" xmi.id="75" type="uint" name="lastModified" />
+ <UML:Operation visibility="public" xmi.id="76" type="QString" name="filename" />
+ <UML:Attribute visibility="private" xmi.id="77" value="" type="uint" name="_lastModified" />
+ <UML:Attribute visibility="private" xmi.id="78" value="" type="QString" name="_categoryName" />
+ <UML:Attribute visibility="private" xmi.id="79" value="" type="QString" name="_filename" />
+ </UML:Class>
+ <UML:DataType stereotype="3" visibility="public" xmi.id="84" name="QMap" />
+ <UML:DataType stereotype="3" visibility="public" xmi.id="86" name="QString" />
+ <UML:DataType stereotype="3" visibility="public" xmi.id="94" name="QPtrList&lt;Memofile>" />
+ <UML:Association visibility="public" xmi.id="36" >
+ <UML:Association.connection>
+ <UML:AssociationEndRole visibility="public" aggregation="composite" type="11" />
+ <UML:AssociationEndRole visibility="private" type="34" />
+ </UML:Association.connection>
+ </UML:Association>
+ </UML:Model>
+ </XMI.content>
+ <XMI.extensions xmi.extender="umbrello" >
+ <docsettings viewid="62" documentation="" uniqueid="107" />
+ <diagrams>
+ <diagram snapgrid="0" showattsig="1" fillcolor="#ffffc0" linewidth="0" zoom="100" showgrid="0" showopsig="1" usefillcolor="1" snapx="10" canvaswidth="807" snapy="10" showatts="1" xmi.id="1" documentation="" type="402" showops="1" showpackage="0" name="class diagram" localid="30000" showstereotype="0" showscope="1" snapcsgrid="0" font="Sans,10,-1,5,50,0,0,0,0,0" linecolor="#ff0000" canvasheight="591" >
+ <widgets/>
+ <messages/>
+ <associations/>
+ </diagram>
+ <diagram snapgrid="0" showattsig="1" fillcolor="#ffffc0" linewidth="0" zoom="100" showgrid="0" showopsig="1" usefillcolor="1" snapx="10" canvaswidth="999" snapy="10" showatts="1" xmi.id="62" documentation="" type="402" showops="1" showpackage="0" name="memofile classes" localid="30000" showstereotype="0" showscope="1" snapcsgrid="0" font="Sans,10,-1,5,50,0,0,0,0,0" linecolor="#ff0000" canvasheight="630" >
+ <widgets>
+ <classwidget usesdiagramfillcolour="1" width="543" showattsigs="601" usesdiagramusefillcolour="1" x="428" linecolour="none" y="62" showopsigs="601" linewidth="none" usesdiagramlinewidth="1" usesdiagramlinecolour="1" fillcolour="none" height="544" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="11" showoperations="1" showpackage="0" showscope="1" showstereotype="0" font="Sans,10,-1,5,75,0,0,0,0,0" />
+ <classwidget usesdiagramfillcolour="1" width="432" showattsigs="601" usesdiagramusefillcolour="1" x="17" linecolour="none" y="33" showopsigs="601" linewidth="none" usesdiagramlinewidth="1" usesdiagramlinecolour="1" fillcolour="none" height="255" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="63" showoperations="1" showpackage="0" showscope="1" showstereotype="0" font="Sans,10,-1,5,75,0,0,0,0,0" />
+ <classwidget usesdiagramfillcolour="1" width="767" showattsigs="601" usesdiagramusefillcolour="1" x="3" linecolour="none" y="467" showopsigs="601" linewidth="none" usesdiagramlinewidth="1" usesdiagramlinecolour="1" fillcolour="none" height="136" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="64" showoperations="1" showpackage="0" showscope="1" showstereotype="0" font="Sans,10,-1,5,75,0,0,0,0,0" />
+ </widgets>
+ <messages/>
+ <associations/>
+ </diagram>
+ </diagrams>
+ <listview>
+ <listitem open="1" type="800" id="-1" label="Views" >
+ <listitem open="1" type="801" id="-1" label="Logical View" >
+ <listitem open="0" type="807" id="1" label="class diagram" />
+ <listitem open="0" type="807" id="62" label="memofile classes" />
+ <listitem open="0" type="813" id="64" >
+ <listitem open="0" type="814" id="78" />
+ <listitem open="0" type="814" id="79" />
+ <listitem open="0" type="814" id="77" />
+ <listitem open="0" type="815" id="65" />
+ <listitem open="0" type="815" id="68" />
+ <listitem open="0" type="815" id="76" />
+ <listitem open="0" type="815" id="75" />
+ </listitem>
+ <listitem open="0" type="813" id="11" >
+ <listitem open="1" type="813" id="34" />
+ <listitem open="0" type="814" id="29" />
+ <listitem open="0" type="814" id="30" />
+ <listitem open="0" type="814" id="31" />
+ <listitem open="0" type="814" id="40" />
+ <listitem open="0" type="814" id="41" />
+ <listitem open="0" type="814" id="33" />
+ <listitem open="0" type="814" id="32" />
+ <listitem open="0" type="814" id="37" />
+ <listitem open="0" type="814" id="42" />
+ <listitem open="0" type="814" id="38" />
+ <listitem open="0" type="814" id="39" />
+ <listitem open="0" type="815" id="12" />
+ <listitem open="0" type="815" id="52" />
+ <listitem open="0" type="815" id="55" />
+ <listitem open="0" type="815" id="54" />
+ <listitem open="0" type="815" id="26" />
+ <listitem open="0" type="815" id="44" />
+ <listitem open="0" type="815" id="45" />
+ <listitem open="0" type="815" id="50" />
+ <listitem open="0" type="815" id="47" />
+ <listitem open="0" type="815" id="51" />
+ <listitem open="0" type="815" id="27" />
+ <listitem open="0" type="815" id="49" />
+ <listitem open="0" type="815" id="48" />
+ <listitem open="0" type="815" id="28" />
+ <listitem open="0" type="815" id="43" />
+ <listitem open="0" type="815" id="59" />
+ <listitem open="0" type="815" id="56" />
+ <listitem open="0" type="815" id="57" />
+ <listitem open="0" type="815" id="58" />
+ <listitem open="0" type="815" id="16" />
+ <listitem open="1" type="831" id="17" />
+ </listitem>
+ <listitem open="1" type="813" id="63" >
+ <listitem open="0" type="814" id="85" />
+ <listitem open="0" type="814" id="83" />
+ <listitem open="0" type="814" id="93" />
+ <listitem open="0" type="815" id="80" />
+ <listitem open="0" type="815" id="102" />
+ <listitem open="0" type="815" id="97" />
+ <listitem open="0" type="815" id="91" />
+ <listitem open="0" type="815" id="99" />
+ <listitem open="0" type="815" id="89" />
+ <listitem open="0" type="815" id="104" />
+ <listitem open="0" type="815" id="87" />
+ <listitem open="0" type="815" id="98" />
+ <listitem open="0" type="815" id="90" />
+ <listitem open="0" type="815" id="95" />
+ </listitem>
+ <listitem open="0" type="830" id="-1" label="Datatypes" >
+ <listitem open="1" type="829" id="84" />
+ <listitem open="1" type="829" id="94" />
+ <listitem open="1" type="829" id="86" />
+ <listitem open="1" type="829" id="5" />
+ <listitem open="1" type="829" id="4" />
+ <listitem open="1" type="829" id="7" />
+ <listitem open="1" type="829" id="6" />
+ <listitem open="1" type="829" id="2" />
+ <listitem open="1" type="829" id="8" />
+ <listitem open="1" type="829" id="9" />
+ <listitem open="1" type="829" id="10" />
+ </listitem>
+ </listitem>
+ <listitem open="1" type="802" id="-1" label="Use Case View" />
+ <listitem open="1" type="821" id="-1" label="Component View" />
+ <listitem open="1" type="827" id="-1" label="Deployment View" />
+ </listitem>
+ </listview>
+ <codegeneration/>
+ </XMI.extensions>
+</XMI>
diff --git a/kpilot/conduits/memofileconduit/memofiles.cc b/kpilot/conduits/memofileconduit/memofiles.cc
new file mode 100644
index 000000000..2846d448b
--- /dev/null
+++ b/kpilot/conduits/memofileconduit/memofiles.cc
@@ -0,0 +1,700 @@
+/* memofile-conduit.cc KPilot
+**
+** Copyright (C) 2004-2007 by Jason 'vanRijn' Kasper
+**
+*/
+
+/*
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU Lesser General Public License as published by
+** the Free Software Foundation; either version 2.1 of the License, or
+** (at your option) any later version.
+**
+** This 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 Lesser General Public License for more details.
+**
+** You should have received a copy of the GNU Lesser General Public License
+** along with this program in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include "options.h"
+
+#include "memofiles.h"
+#include "memofile.h"
+
+QString Memofiles::FIELD_SEP = CSL1("\t");
+
+Memofiles::Memofiles (MemoCategoryMap & categories, PilotMemoInfo &appInfo,
+ QString & baseDirectory, CUDCounter &fCtrPC) :
+ _categories(categories), _memoAppInfo(appInfo),
+ _baseDirectory(baseDirectory), _cudCounter(fCtrPC)
+{
+ FUNCTIONSETUP;
+ _memofiles.clear();
+ _memoMetadataFile = _baseDirectory + QDir::separator() + CSL1(".ids");
+ _categoryMetadataFile = _baseDirectory + QDir::separator() + CSL1(".categories");
+ _memofiles.setAutoDelete(true);
+
+ _ready = ensureDirectoryReady();
+
+ _metadataLoaded = loadFromMetadata();
+}
+
+Memofiles::~Memofiles()
+{
+ FUNCTIONSETUP;
+}
+
+void Memofiles::load (bool loadAll)
+{
+ FUNCTIONSETUP;
+
+ DEBUGKPILOT << fname
+ << ": now looking at all memofiles in your directory." << endl;
+
+ // now go through each of our known categories and look in each directory
+ // for that category for memo files
+ MemoCategoryMap::ConstIterator it;
+ int counter = -1;
+
+ for ( it = _categories.begin(); it != _categories.end(); ++it ) {
+ int category = it.key();
+ QString categoryName = it.data();
+ QString categoryDirname = _baseDirectory + QDir::separator() + categoryName;
+
+ QDir dir = QDir(categoryDirname);
+ if (! dir.exists() ) {
+ DEBUGKPILOT << fname
+ << ": category directory: [" << categoryDirname
+ << "] doesn't exist. skipping." << endl;
+ continue;
+ }
+
+
+ QStringList entries = dir.entryList(QDir::Files);
+ QString file;
+ for(QStringList::Iterator it = entries.begin(); it != entries.end(); ++it) {
+ file = *it;
+ QFileInfo info(dir, file);
+
+ if(info.isFile() && info.isReadable()) {
+// DEBUGKPILOT << fname
+// << ": checking category: [" << categoryName
+// << "], file: [" << file << "]." << endl;
+ Memofile * memofile = find(categoryName, file);
+ if (NULL == memofile) {
+ memofile = new Memofile(category, categoryName, file, _baseDirectory);
+ memofile->setModified(true);
+ _memofiles.append(memofile);
+ DEBUGKPILOT << fname
+ << ": looks like we didn't know about this one until now. "
+ << "created new memofile for category: ["
+ << categoryName << "], file: [" << file << "]." << endl;
+
+ }
+
+ counter++;
+
+ // okay, we should have a memofile for this file now. see if we need
+ // to load its text...
+ if (memofile->isModified() || loadAll) {
+ DEBUGKPILOT << fname
+ << ": now loading text for: [" << info.filePath() << "]." << endl;
+ memofile->load();
+ }
+ } else {
+ DEBUGKPILOT << fname
+ << ": couldn't read file: [" << info.filePath() << "]. skipping it." << endl;
+
+ }
+ } // end of iterating through files in this directory
+
+ } // end of iterating through our categories/directories
+
+ DEBUGKPILOT << fname
+ << ": looked at: [" << counter << "] files from your directories." << endl;
+
+
+ // okay, now we've loaded everything from our directories. make one last
+ // pass through our loaded memofiles and see if we need to mark any of them
+ // as deleted (i.e. we created a memofile object from our metadata, but
+ // the file is now gone, so it's deleted.
+ Memofile * memofile;
+
+ for ( memofile = _memofiles.first(); memofile; memofile = _memofiles.next() ) {
+ if (! memofile->fileExists()) {
+ memofile->setDeleted( true );
+ }
+ }
+}
+
+/**
+* Make sure that our directory is ready to synchronize with our
+* Palm's database. This means we need to make sure that the directory
+* that our user has specified for storing his/her memos exists, as well
+* as a directory inside that directory for each of his/her memo categories.
+*/
+bool Memofiles::ensureDirectoryReady()
+{
+ FUNCTIONSETUP;
+
+ if (!checkDirectory(_baseDirectory))
+ return false;
+
+ int failures = 0;
+ // now make sure that a directory for each category exists.
+ QString _category_name;
+ QString dir;
+
+ MemoCategoryMap::Iterator it;
+ for ( it = _categories.begin(); it != _categories.end(); ++it ) {
+ _category_name = it.data();
+ dir = _baseDirectory + QDir::separator() + _category_name;
+
+ DEBUGKPILOT << fname
+ << ": checking directory: [" << dir << "]" << endl;
+
+ if (!checkDirectory(dir))
+ failures++;
+ }
+
+ return failures == 0;
+}
+
+bool Memofiles::checkDirectory(QString & dir)
+{
+ FUNCTIONSETUP;
+ // make sure that the directory we're asked to write to exists
+ QDir d(dir);
+ QFileInfo fid( dir );
+
+ if ( ! fid.isDir() ) {
+
+ DEBUGKPILOT << fname
+ << ": directory: [" << dir
+ << "] doesn't exist. creating...."
+ << endl;
+
+ if (!d.mkdir(dir)) {
+
+ DEBUGKPILOT << fname
+ << ": could not create directory: [" << dir
+ << "]. this won't end well." << endl;
+ return false;
+ } else {
+ DEBUGKPILOT << fname
+ << ": directory created: ["
+ << dir << "]." << endl;
+
+ }
+ } else {
+ DEBUGKPILOT << fname
+ << ": directory already existed: ["
+ << dir << "]." << endl;
+
+ }
+
+ return true;
+
+}
+
+void Memofiles::eraseLocalMemos ()
+{
+ FUNCTIONSETUP;
+
+ MemoCategoryMap::Iterator it;
+ for ( it = _categories.begin(); it != _categories.end(); ++it ) {
+ QString dir = _baseDirectory + QDir::separator() + it.data();
+
+ if (!folderRemove(QDir(dir))) {
+ DEBUGKPILOT << fname
+ << ": couldn't erase all local memos from: ["
+ << dir << "]." << endl;
+ }
+ }
+ QDir d(_baseDirectory);
+ d.remove(_memoMetadataFile);
+
+ ensureDirectoryReady();
+
+ _memofiles.clear();
+}
+
+void Memofiles::setPilotMemos (QPtrList<PilotMemo> & memos)
+{
+ FUNCTIONSETUP;
+
+ PilotMemo * memo;
+
+ _memofiles.clear();
+
+ for ( memo = memos.first(); memo; memo = memos.next() ) {
+ addModifiedMemo(memo);
+ }
+
+ DEBUGKPILOT << fname
+ << ": set: ["
+ << _memofiles.count() << "] from Palm to local." << endl;
+
+}
+
+bool Memofiles::loadFromMetadata ()
+{
+ FUNCTIONSETUP;
+
+ _memofiles.clear();
+
+ QFile f( _memoMetadataFile );
+ if ( !f.open( IO_ReadOnly ) ) {
+ DEBUGKPILOT << fname
+ << ": ooh, bad. couldn't open your memo-id file for reading."
+ << endl;
+ return false;
+ }
+
+ QTextStream t( &f );
+ Memofile * memofile;
+
+ while ( !t.atEnd() ) {
+ QString data = t.readLine();
+ int errors = 0;
+ bool ok;
+
+ QStringList fields = QStringList::split( FIELD_SEP, data );
+ if ( fields.count() >= 4 ) {
+ int id = fields[0].toInt( &ok );
+ if ( !ok )
+ errors++;
+ int category = fields[1].toInt( &ok );
+ if ( !ok )
+ errors++;
+ uint lastModified = fields[2].toInt( &ok );
+ if ( !ok )
+ errors++;
+ uint size = fields[3].toInt( &ok );
+ if ( !ok )
+ errors++;
+ QString filename = fields[4];
+ if ( filename.isEmpty() )
+ errors++;
+
+ if (errors <= 0) {
+ memofile = new Memofile(id, category, lastModified, size,
+ _categories[category], filename, _baseDirectory);
+ _memofiles.append(memofile);
+ // DEBUGKPILOT << fname
+ // << ": created memofile from metadata. id: [" << id
+ // << "], category: ["
+ // << _categories[category] << "], filename: [" << filename << "]."
+ // << endl;
+ }
+ } else {
+ errors++;
+ }
+
+ if (errors > 0) {
+ DEBUGKPILOT << fname
+ << ": error: couldn't understand this line: [" << data << "]."
+ << endl;
+ }
+ }
+
+ DEBUGKPILOT << fname
+ << ": loaded: [" << _memofiles.count() << "] memofiles."
+ << endl;
+
+ f.close();
+
+ return true;
+}
+
+Memofile * Memofiles::find (recordid_t id)
+{
+
+ Memofile * memofile;
+
+ for ( memofile = _memofiles.first(); memofile; memofile = _memofiles.next() ) {
+ if ( memofile->id() == id) {
+ return memofile;
+ }
+ }
+
+ return NULL;
+
+}
+
+Memofile * Memofiles::find (const QString & category, const QString & filename)
+{
+
+ Memofile * memofile;
+
+ for ( memofile = _memofiles.first(); memofile; memofile = _memofiles.next() ) {
+ if ( memofile->getCategoryName() == category &&
+ memofile->getFilename() == filename ) {
+ return memofile;
+ }
+ }
+
+ return NULL;
+
+}
+
+void Memofiles::deleteMemo(PilotMemo * memo)
+{
+ FUNCTIONSETUP;
+ if (! memo->isDeleted())
+ return;
+
+ Memofile * memofile = find(memo->id());
+ if (memofile) {
+ memofile->deleteFile();
+ _memofiles.remove(memofile);
+ _cudCounter.deleted();
+ }
+}
+
+
+void Memofiles::addModifiedMemo (PilotMemo * memo)
+{
+ FUNCTIONSETUP;
+
+ if (memo->isDeleted()) {
+ deleteMemo(memo);
+ return;
+ }
+
+ QString debug = CSL1(": adding a PilotMemo. id: [")
+ + QString::number(memo->id()) + CSL1("], title: [")
+ + memo->getTitle() + CSL1("]. ");
+
+ Memofile * memofile = find(memo->id());
+
+ if (NULL == memofile) {
+ _cudCounter.created();
+ debug += CSL1(" new from pilot.");
+ } else {
+ // we have found a local memofile that was modified on the palm. for the time
+ // being (until someone complains, etc.), we will always overwrite changes to
+ // the local filesystem with changes to the palm (palm overrides local). at
+ // some point in the future, we should probably honor a user preference for
+ // this...
+ _cudCounter.updated();
+ _memofiles.remove(memofile);
+ debug += CSL1(" modified from pilot.");
+ }
+
+ DEBUGKPILOT << fname
+ << debug << endl;
+
+ memofile = new Memofile(memo, _categories[memo->category()], filename(memo), _baseDirectory);
+ memofile->setModifiedByPalm(true);
+ _memofiles.append(memofile);
+
+}
+
+QPtrList<Memofile> Memofiles::getModified ()
+{
+ FUNCTIONSETUP;
+
+ QPtrList<Memofile> modList;
+ modList.clear();
+
+ Memofile * memofile;
+
+ for ( memofile = _memofiles.first(); memofile; memofile = _memofiles.next() ) {
+ if ( memofile->isModified() && ! memofile->isModifiedByPalm() ) {
+ modList.append(memofile);
+ }
+ }
+
+ DEBUGKPILOT << fname
+ << ": found: [" << modList.count() << "] memofiles modified on filesystem." << endl;
+
+ return modList;
+}
+
+void Memofiles::save()
+{
+ FUNCTIONSETUP;
+
+ saveCategoryMetadata();
+ saveMemos();
+ // this needs to be done last, because saveMemos() might change
+ // attributes of the Memofiles
+ saveMemoMetadata();
+
+}
+
+bool Memofiles::saveMemoMetadata()
+{
+ FUNCTIONSETUP;
+
+ DEBUGKPILOT << fname
+ << ": saving memo metadata to file: ["
+ << _memoMetadataFile << "]" << endl;
+
+ QFile f( _memoMetadataFile );
+ QTextStream stream(&f);
+
+ if( !f.open(IO_WriteOnly) ) {
+ DEBUGKPILOT << fname
+ << ": ooh, bad. couldn't open your memo-id file for writing."
+ << endl;
+ return false;
+ }
+
+ Memofile * memofile;
+
+ // each line looks like this, but FIELD_SEP is the separator instead of ","
+ // id,category,lastModifiedTime,filesize,filename
+ for ( memofile = _memofiles.first(); memofile; memofile = _memofiles.next() ) {
+ // don't save deleted memos to our id file
+ if (! memofile->isDeleted()) {
+ stream << memofile->id() << FIELD_SEP
+ << memofile->category() << FIELD_SEP
+ << memofile->lastModified() << FIELD_SEP
+ << memofile->size() << FIELD_SEP
+ << memofile->filename()
+ << endl;
+ }
+ }
+
+ f.close();
+
+ return true;
+
+}
+
+MemoCategoryMap Memofiles::readCategoryMetadata()
+{
+ FUNCTIONSETUP;
+
+ DEBUGKPILOT << fname
+ << ": reading categories from file: ["
+ << _categoryMetadataFile << "]" << endl;
+
+ MemoCategoryMap map;
+ map.clear();
+
+ QFile f( _categoryMetadataFile );
+ QTextStream stream(&f);
+
+ if( !f.open(IO_ReadOnly) ) {
+ DEBUGKPILOT << fname
+ << ": ooh, bad. couldn't open your categories file for reading."
+ << endl;
+ return map;
+ }
+
+
+ while ( !stream.atEnd() ) {
+ QString data = stream.readLine();
+ int errors = 0;
+ bool ok;
+
+ QStringList fields = QStringList::split( FIELD_SEP, data );
+ if ( fields.count() >= 2 ) {
+ int id = fields[0].toInt( &ok );
+ if ( !ok )
+ errors++;
+ QString categoryName = fields[1];
+ if ( categoryName.isEmpty() )
+ errors++;
+
+ if (errors <= 0) {
+ map[id] = categoryName;
+ }
+ } else {
+ errors++;
+ }
+
+ if (errors > 0) {
+ DEBUGKPILOT << fname
+ << ": error: couldn't understand this line: [" << data << "]."
+ << endl;
+ }
+ }
+
+ DEBUGKPILOT << fname
+ << ": loaded: [" << map.count() << "] categories."
+ << endl;
+
+ f.close();
+
+ return map;
+}
+
+bool Memofiles::saveCategoryMetadata()
+{
+ FUNCTIONSETUP;
+
+
+ DEBUGKPILOT << fname
+ << ": saving categories to file: ["
+ << _categoryMetadataFile << "]" << endl;
+
+ QFile f( _categoryMetadataFile );
+ QTextStream stream(&f);
+
+ if( !f.open(IO_WriteOnly) ) {
+ DEBUGKPILOT << fname
+ << ": ooh, bad. couldn't open your categories file for writing."
+ << endl;
+ return false;
+ }
+
+ MemoCategoryMap::Iterator it;
+ for ( it = _categories.begin(); it != _categories.end(); ++it ) {
+ stream << it.key()
+ << FIELD_SEP
+ << it.data()
+ << endl;
+ }
+
+ f.close();
+
+ return true;
+}
+
+bool Memofiles::saveMemos()
+{
+ FUNCTIONSETUP;
+
+ Memofile * memofile;
+ bool result = true;
+
+ for ( memofile = _memofiles.first(); memofile; memofile = _memofiles.next() ) {
+ if (memofile->isDeleted()) {
+ _memofiles.remove(memofile);
+ } else {
+ result = memofile->save();
+ // Fix prompted by Bug #103922
+ // if we weren't able to save the file, then remove it from the list.
+ // if we don't do this, the next sync will think that the user deliberately
+ // deleted the memofile and will then delete it from the Pilot.
+ // TODO -- at some point, we should probably tell the user that this
+ // did not work, but that will require a String change.
+ // Also, this is a partial fix since at this point
+ // this memo will never make its way onto the PC, but at least
+ // we won't delete it from the Pilot erroneously either. *sigh*
+ if (!result) {
+ DEBUGKPILOT << fname
+ << ": unable to save memofile: ["
+ << memofile->filename()
+ << "], now removing it from the metadata list."
+ << endl;
+ _memofiles.remove(memofile);
+ }
+ }
+ }
+ return true;
+}
+
+bool Memofiles::isFirstSync()
+{
+ FUNCTIONSETUP;
+ bool metadataExists = QFile::exists(_memoMetadataFile) &&
+ QFile::exists(_categoryMetadataFile);
+
+ bool valid = metadataExists && _metadataLoaded;
+
+ DEBUGKPILOT << fname
+ << ": local metadata exists: [" << metadataExists
+ << "], metadata loaded: [" << _metadataLoaded
+ << "], returning: [" << ! valid << "]" << endl;
+ return ! valid;
+}
+
+
+
+bool Memofiles::folderRemove(const QDir &_d)
+{
+ FUNCTIONSETUP;
+
+ QDir d = _d;
+
+ QStringList entries = d.entryList();
+ for(QStringList::Iterator it = entries.begin(); it != entries.end(); ++it) {
+ if(*it == CSL1(".") || *it == CSL1(".."))
+ continue;
+ QFileInfo info(d, *it);
+ if(info.isDir()) {
+ if(!folderRemove(QDir(info.filePath())))
+ return FALSE;
+ } else {
+ DEBUGKPILOT << fname
+ << ": deleting file: [" << info.filePath() << "]" << endl;
+ d.remove(info.filePath());
+ }
+ }
+ QString name = d.dirName();
+ if(!d.cdUp())
+ return FALSE;
+ DEBUGKPILOT << fname
+ << ": removing folder: [" << name << "]" << endl;
+ d.rmdir(name);
+
+ return TRUE;
+}
+
+QString Memofiles::filename(PilotMemo * memo)
+{
+ FUNCTIONSETUP;
+
+ QString filename = memo->getTitle();
+
+ if (filename.isEmpty()) {
+ QString text = memo->text();
+ int i = text.find(CSL1("\n"));
+ if (i > 1) {
+ filename = text.left(i);
+ }
+ if (filename.isEmpty()) {
+ filename = CSL1("empty");
+ }
+ }
+
+ filename = sanitizeName(filename);
+
+ QString category = _categories[memo->category()];
+
+ Memofile * memofile = find(category, filename);
+
+ // if we couldn't find a memofile with this filename, or if the
+ // memofile that is found is the same as the memo that we're looking
+ // at, then use the filename
+ if (NULL == memofile || memofile == memo) {
+ return filename;
+ }
+
+ int uniq = 2;
+ QString newfilename;
+
+ // try to find a good filename, but only do this 20 times at the most.
+ // if our user has 20 memos with the same filename, he/she is asking
+ // for trouble.
+ while (NULL != memofile && uniq <=20) {
+ newfilename = QString(filename + CSL1(".") + QString::number(uniq++) );
+ memofile = find(category, newfilename);
+ }
+
+ return newfilename;
+}
+
+QString Memofiles::sanitizeName(QString name)
+{
+ QString clean = name;
+ // safety net. we can't save a
+ // filesystem separator as part of a filename, now can we?
+ clean.replace('/', CSL1("-"));
+ return clean;
+}
+
diff --git a/kpilot/conduits/memofileconduit/memofiles.h b/kpilot/conduits/memofileconduit/memofiles.h
new file mode 100644
index 000000000..ec0497d5b
--- /dev/null
+++ b/kpilot/conduits/memofileconduit/memofiles.h
@@ -0,0 +1,96 @@
+#ifndef _MEMOFILE_MEMOFILES_H
+#define _MEMOFILE_MEMOFILES_H
+/* memofiles.h KPilot
+**
+** Copyright (C) 2004-2007 by Jason 'vanRijn' Kasper
+*/
+
+/*
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU Lesser General Public License as published by
+** the Free Software Foundation; either version 2.1 of the License, or
+** (at your option) any later version.
+**
+** This 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 Lesser General Public License for more details.
+**
+** You should have received a copy of the GNU Lesser General Public License
+** along with this program in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include "plugin.h"
+#include <qmap.h>
+
+#include "memofile.h"
+
+typedef QMap<int, QString> MemoCategoryMap;
+
+class Memofile;
+
+class Memofiles {
+
+public:
+
+ Memofiles (MemoCategoryMap & categories, PilotMemoInfo &appInfo,
+ QString & baseDirectory, CUDCounter &fCtrHH);
+ ~Memofiles();
+
+ void load(bool loadAll);
+ void save();
+ void eraseLocalMemos();
+ void setPilotMemos (QPtrList<PilotMemo> & memos);
+ void addModifiedMemo (PilotMemo * memo);
+ void deleteMemo (PilotMemo * memo);
+
+ bool isFirstSync();
+ bool isReady() { return _ready; };
+
+ QPtrList<Memofile> getModified();
+ QPtrList<Memofile> getAll() { return _memofiles; } ;
+ Memofile * find (const QString & category, const QString & filename);
+ Memofile * find (recordid_t id);
+
+ MemoCategoryMap readCategoryMetadata();
+ void setCategories(MemoCategoryMap map) { _categories = map; } ;
+
+ static QString FIELD_SEP;
+ static QString sanitizeName(QString name);
+
+ int count() { return _memofiles.count(); }
+
+private:
+
+ MemoCategoryMap _categories;
+ PilotMemoInfo &_memoAppInfo;
+ QString & _baseDirectory;
+ CUDCounter &_cudCounter;
+ QPtrList<Memofile> _memofiles;
+
+ bool loadFromMetadata();
+ bool ensureDirectoryReady();
+ bool checkDirectory(QString & dir);
+ bool saveMemoMetadata();
+ bool saveCategoryMetadata();
+ bool saveMemos();
+ bool folderRemove(const QDir & dir);
+
+ QString filename(PilotMemo * memo);
+
+
+ QString _categoryMetadataFile;
+ QString _memoMetadataFile;
+
+ bool _metadataLoaded;
+ bool _ready;
+
+};
+#endif //MEMOFILES_H
+
diff --git a/kpilot/conduits/memofileconduit/setup_base.ui b/kpilot/conduits/memofileconduit/setup_base.ui
new file mode 100644
index 000000000..215c18057
--- /dev/null
+++ b/kpilot/conduits/memofileconduit/setup_base.ui
@@ -0,0 +1,143 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>MemofileWidget</class>
+<comment>A tabWidget for configuring
+the Memofile-conduit settings.</comment>
+<author>Jason 'vanRijn' Kasper</author>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>Form1</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>342</width>
+ <height>412</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="baseSize">
+ <size>
+ <width>570</width>
+ <height>270</height>
+ </size>
+ </property>
+ <property name="caption">
+ <string>Memofile Conduit Options</string>
+ </property>
+ <property name="layoutMargin" stdset="0">
+ </property>
+ <property name="layoutSpacing" stdset="0">
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QTabWidget" row="0" column="0">
+ <property name="name">
+ <cstring>tabWidget</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="layoutMargin" stdset="0">
+ </property>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>Widget2</cstring>
+ </property>
+ <attribute name="title">
+ <string>General</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer row="2" column="2">
+ <property name="name">
+ <cstring>Spacer4</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>180</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Sync private records:</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Memos directory:</string>
+ </property>
+ </widget>
+ <widget class="KURLRequester" row="0" column="1" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>fDirectory</cstring>
+ </property>
+ <property name="mode">
+ <number>18</number>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Select the directory you want to store your PDA's memos in</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="1" column="1">
+ <property name="name">
+ <cstring>fSyncPrivate</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </widget>
+ </grid>
+</widget>
+<tabstops>
+ <tabstop>tabWidget</tabstop>
+</tabstops>
+<layoutdefaults spacing="6" margin="11"/>
+<includes>
+ <include location="global" impldecl="in implementation">kurlrequester.h</include>
+ <include location="global" impldecl="in implementation">klineedit.h</include>
+ <include location="global" impldecl="in implementation">kpushbutton.h</include>
+</includes>
+</UI>
diff --git a/kpilot/conduits/notepadconduit/CMakeLists.txt b/kpilot/conduits/notepadconduit/CMakeLists.txt
new file mode 100644
index 000000000..90e202d60
--- /dev/null
+++ b/kpilot/conduits/notepadconduit/CMakeLists.txt
@@ -0,0 +1,38 @@
+include_directories(
+ ${CMAKE_CURRENT_BINARY_DIR}
+)
+
+set(conduit_notepad_SRCS
+ notepad-factory.cc
+ notepad-conduit.cc
+)
+
+set(conduit_notepad_UIS
+ notepad-setup.ui
+)
+
+set(conduit_notepad_KCFGS
+ notepadconduit.kcfgc
+)
+
+kde3_add_kcfg_files(conduit_notepad_SRCS ${conduit_notepad_KCFGS})
+kde3_add_ui_files(conduit_notepad_SRCS ${conduit_notepad_UIS})
+kde3_automoc(${conduit_notepad_SRCS})
+add_library(conduit_notepad SHARED ${conduit_notepad_SRCS})
+
+set_target_properties(
+ conduit_notepad PROPERTIES LOCATION ${KDE3_PLUGIN_INSTALL_DIR}
+ INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/lib
+ PREFIX ""
+)
+
+kde3_install_libtool_file(conduit_notepad)
+
+install(
+ TARGETS conduit_notepad
+ LIBRARY DESTINATION ${KDE3_PLUGIN_INSTALL_DIR}
+)
+
+install(
+ FILES notepad-conduit.desktop DESTINATION ${KDE3_SERVICES_DIR}
+)
diff --git a/kpilot/conduits/notepadconduit/Makefile.am b/kpilot/conduits/notepadconduit/Makefile.am
new file mode 100644
index 000000000..d50e4fd48
--- /dev/null
+++ b/kpilot/conduits/notepadconduit/Makefile.am
@@ -0,0 +1,14 @@
+INCLUDES= $(PISOCK_INCLUDE) -I$(top_srcdir)/kpilot/lib $(all_includes)
+
+METASOURCES = AUTO
+
+servicedir = $(kde_servicesdir)
+service_DATA = notepad-conduit.desktop
+
+kde_module_LTLIBRARIES = conduit_notepad.la
+
+conduit_notepad_la_SOURCES = notepadconduit.kcfgc notepad-setup.ui \
+ notepad-conduit.cc notepad-factory.cc
+conduit_notepad_la_LDFLAGS= -module $(KDE_PLUGIN) $(all_libraries)
+conduit_notepad_la_LIBADD= ../../lib/libkpilot.la $(LIB_KDEUI) $(LIB_KIO)
+
diff --git a/kpilot/conduits/notepadconduit/notepad-conduit.cc b/kpilot/conduits/notepadconduit/notepad-conduit.cc
new file mode 100644
index 000000000..763f3acd0
--- /dev/null
+++ b/kpilot/conduits/notepadconduit/notepad-conduit.cc
@@ -0,0 +1,265 @@
+/* KPilot
+**
+** Copyright (C) 2004 by Adriaan de Groot, Joern Ahrens
+**
+** The code for NotepadActionThread::unpackNotePad was taken from
+** Angus Ainslies read-notepad.c, which is part of pilot-link.
+** NotepadActionThread::saveImage is also based on read-notepad.c.
+**
+** This file is part of the Notepad conduit, a conduit for KPilot that
+** stores the notepad drawings to files.
+*/
+
+/*
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU Lesser General Public License as published by
+** the Free Software Foundation; either version 2.1 of the License, or
+** (at your option) any later version.
+**
+** This 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 Lesser General Public License for more details.
+**
+** You should have received a copy of the GNU Lesser General Public License
+** along with this program in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include "options.h"
+#include "pilotUser.h"
+#include "pilotSerialDatabase.h"
+
+#include "notepad-conduit.h" // The Conduit action
+#include "notepadconduit.h" // The settings class
+
+#include <pi-notepad.h>
+
+#include <qthread.h>
+#include <qapplication.h>
+#include <qvaluelist.h>
+#include <qimage.h>
+#include <qdir.h>
+#include <qcstring.h>
+
+extern "C"
+{
+unsigned long version_conduit_notepad = Pilot::PLUGIN_API;
+}
+
+NotepadConduit::NotepadConduit(KPilotLink *d, const char *n,
+ const QStringList &args) : ConduitAction(d, n, args)
+{
+ FUNCTIONSETUP;
+ fConduitName=i18n("Notepad");
+ thread = 0L;
+
+}
+
+NotepadConduit::~NotepadConduit()
+{
+ FUNCTIONSETUP;
+}
+
+/* virtual */ bool NotepadConduit::exec()
+{
+ FUNCTIONSETUP;
+
+#ifdef DEBUG
+ DEBUGKPILOT << fname << ": In exec() @" << (unsigned long) this << endl;
+#endif
+
+ QDir dir(NotepadConduitSettings::outputDirectory());
+ if(!dir.exists() && !dir.mkdir(dir.path())) {
+ emit logError(i18n("Unable to open %1").arg(dir.path()));
+ delayDone();
+ return false;
+ }
+ else {
+ thread = new NotepadActionThread(this, deviceLink());
+ thread->start();
+ // tickle is disabled due to crashs during sync
+ // -> PADP TX "unexpected package"
+// startTickle();
+ }
+
+ return true;
+}
+
+bool NotepadConduit::event(QEvent *e)
+{
+ FUNCTIONSETUP;
+
+ if(e->type() == QEvent::User) {
+#ifdef DEBUG
+ DEBUGKPILOT << fname << ": Notepad thread done." << endl;
+#endif
+// stopTickle();
+ delayDone();
+ if(thread->getFailed())
+ logError(i18n("1 notepad could not be saved", "%n notepads could not be saved", thread->getFailed()));
+ logMessage(i18n("1 notepad saved", "%n notepads saved", thread->getSaved()));
+ delete thread;
+ return true;
+ }
+ else
+ return ConduitAction::event(e);
+}
+
+//-----------------------------------------------------------------------------
+// NotepadActionThread
+//-----------------------------------------------------------------------------
+
+NotepadActionThread::NotepadActionThread(QObject *parent, KPilotLink *link) :
+ fParent(parent), fLink(link), notSaved(0), saved(0)
+{
+ FUNCTIONSETUP;
+}
+
+void NotepadActionThread::run()
+{
+ FUNCTIONSETUP;
+
+ PilotDatabase *db = fLink->database( CSL1("npadDB") );
+
+ int n = db->recordCount();
+
+ if ( n > 0 )
+ {
+ QValueList<recordid_t> vl = db->idList();
+ QValueList<recordid_t>::iterator it;
+ struct NotePad a;
+ for ( it = vl.begin(); it != vl.end(); ++it )
+ {
+ PilotRecord *pr = db->readRecordById(*it);
+ if(pr)
+ {
+ unpack_NotePad(&a, (unsigned char*)pr->data(), pr->size());
+ saveImage(&a);
+ free_NotePad(&a);
+ }
+ }
+ }
+ KPILOT_DELETE(db);
+ QApplication::postEvent(fParent, new QEvent(QEvent::User));
+}
+
+static void saveImageFromBITS(QImage &image, struct NotePad *n, unsigned int width)
+{
+ FUNCTIONSETUP;
+ image.setColor(0, qRgb(0xaa, 0xc1 ,0x91));
+ image.setColor(1, qRgb(0x30, 0x36, 0x29));
+
+ int x = 0;
+ int y = 0;
+ int pos = 0;
+ for(unsigned int i=0; i<n->body.dataLen/2; ++i)
+ {
+ for(int j=0; j<n->data[i].repeat; ++j)
+ {
+ for(int k=0; k<8; ++k)
+ {
+ y = pos / width;
+ x = pos % width ;
+
+ image.setPixel( x, y,
+ (n->data[i].data & 1<<(7-k)) ? 1 : 0 );
+ ++pos;
+ }
+ }
+ }
+}
+
+static void saveImageFromUNCOMPRESSED(QImage &image, struct NotePad *n, unsigned int width)
+{
+ FUNCTIONSETUP;
+
+ image.setColor(0, qRgb(0xaa, 0xc1 ,0x91));
+ image.setColor(1, qRgb(0x30, 0x36, 0x29));
+
+ unsigned int pos = 0;
+ unsigned int x,y;
+
+ for (unsigned int i=0; i<n->body.dataLen / 2; ++i)
+ {
+ for (unsigned int k=0; k<8; ++k)
+ {
+ y = pos / width;
+ x = pos % width ;
+
+ image.setPixel( x, y,
+ (n->data[i].repeat & 1<<(7-k)) ? 1 : 0 );
+ ++pos;
+ }
+
+ for (unsigned int k=0; k<8; ++k)
+ {
+ y = pos / width;
+ x = pos % width ;
+
+ image.setPixel( x, y,
+ (n->data[i].data & 1<<(7-k)) ? 1 : 0 );
+ ++pos;
+ }
+ }
+}
+
+void NotepadActionThread::saveImage(struct NotePad *n)
+{
+ FUNCTIONSETUP;
+
+ // Width needs adjusting, based on whether it's low res (+8)
+ // or a hi-res notepad image.
+ int width = n->body.width + ( n->body.width > 160 ? 16 : 8 );
+ int height = n->body.height;
+
+
+ QImage image(width, height, 8, 2);
+
+ switch (n->body.dataType)
+ {
+ case NOTEPAD_DATA_BITS :
+ saveImageFromBITS( image,n,width );
+ break;
+ case NOTEPAD_DATA_UNCOMPRESSED :
+ saveImageFromUNCOMPRESSED( image,n,width );
+ break;
+ case NOTEPAD_DATA_PNG :
+ image.loadFromData((uchar*)(n->data), n->body.dataLen);
+ break;
+ default :
+ // Unknown data type
+ WARNINGKPILOT << "Unknown data type: " << n->body.dataType << endl;
+ return;
+
+ // TODO: Post a warning to the UI
+ }
+
+ QString filename(n->name);
+ if(filename.isEmpty())
+ {
+ filename.sprintf("%4d-%02d-%02d_%02d-%02d-%02d",
+ n->changeDate.year,
+ n->changeDate.month,
+ n->changeDate.day,
+ n->changeDate.hour,
+ n->changeDate.min,
+ n->changeDate.sec);
+ }
+ QString imgname = QString("%1/%2.png").arg(NotepadConduitSettings::outputDirectory()).arg(filename);
+
+
+#ifdef DEBUG
+ DEBUGKPILOT << fname << ": Notepad " << imgname << endl;
+#endif
+ if(!image.save(imgname, "PNG", -1))
+ ++notSaved;
+ else
+ ++saved;
+}
+
diff --git a/kpilot/conduits/notepadconduit/notepad-conduit.desktop b/kpilot/conduits/notepadconduit/notepad-conduit.desktop
new file mode 100644
index 000000000..4aa10dbee
--- /dev/null
+++ b/kpilot/conduits/notepadconduit/notepad-conduit.desktop
@@ -0,0 +1,65 @@
+[Desktop Entry]
+Type=Service
+Name=NotePad
+Name[cs]=Poznámkový blok
+Name[da]=Notesblok
+Name[de]=Notizen
+Name[es]=Bloc de notas
+Name[fi]=Muistio
+Name[fr]=Notes
+Name[gl]=Caderno de Notas
+Name[hu]=Notepad
+Name[nb]=NotisBlokk
+Name[ne]=नोटपà¥à¤¯à¤¾à¤¡
+Name[nn]=NotisBlokk
+Name[pl]=Notatnik
+Name[sv]=Anteckningar
+Name[ta]=நோடà¯à®ªà¯‡à®Ÿà¯
+Name[tg]=Эзоҳот
+Name[zh_CN]=记事本
+Comment=This conduit backs up NotePad drawings to a local folder.
+Comment[af]=Hierdie pad sinkroniseer NotePad tekeninge na 'n plaaslike gids.
+Comment[bg]=Създаване на архивни ÐºÐ¾Ð¿Ð¸Ñ Ð½Ð° изображениÑта Ñъздадени Ñ NotePad в локална директориÑ.
+Comment[ca]=Aquest conducte copia els dibuixos NotePad a una carpeta local.
+Comment[cs]=Toto propojení synchronizuje záznamy v PDA s lokálním adresářem.
+Comment[da]=Denne kanal sikkerhedskopierer NotePad's tegninger til en lokal mappe.
+Comment[de]=Diese Erweiterung (Conduit) sichert NotePad-Zeichnungen in einen lokalen Ordner.
+Comment[el]=Αυτός ο σÏνδεσμος δημιουÏγεί αντίγÏαφα ασφαλείας σχεδίων του NotePad σε έναν τοπικό φάκελο.
+Comment[es]=Este conducto copia los dibujos del bloc de notas en una carpeta local.
+Comment[et]=See kanal teeb NotePadi joonistustest varukoopia kohalikku kataloogi.
+Comment[eu]=Kanal honek Ohar-blokaren marrazkiak karpeta lokal batera gordetzen ditu.
+Comment[fa]=این لوله، ترسیمهای NotePad را در پوشه‌ای محلی پشتیبانی می‌کند.
+Comment[fi]=Tämä yhdyskäytävä tekee varmuuskopion NotePad -piirroksista paikalliseen kansioon.
+Comment[fr]=Ce conduit enregistre les dessins (Notes) dans un dossier local.
+Comment[fy]=Dit conduit makket in reservekopy fan de notysje fan de notysje-oantekenings nei in lokale map.
+Comment[gl]=Este conducto pon de volta os debuxos do NotePad a un cartafol local.
+Comment[hu]=Bővítőmodul NotePad-rajzok helyi könyvtárba való lementéséhez.
+Comment[is]=Þessi rás afritar NotePad teikningar í staðbundna möppu.
+Comment[it]=Questo conduit archivia i disegni NotePad in una cartella locale.
+Comment[ja]=ã“ã®ã‚³ãƒ³ã‚¸ãƒƒãƒˆã¯ NotePad ã®çµµã‚’ローカルã®ãƒ•ã‚©ãƒ«ãƒ€ã«ãƒãƒƒã‚¯ã‚¢ãƒƒãƒ—ã—ã¾ã™ã€‚
+Comment[ka]=ეს áƒáƒ áƒ®áƒ˜ ლáƒáƒ™áƒáƒšáƒ£áƒ  სáƒáƒ¥áƒáƒ¦áƒáƒšáƒ“ეში ინáƒáƒ®áƒáƒ•áƒ¡ NotePad-ის სáƒáƒ áƒ”ზერვრმáƒáƒœáƒáƒ®áƒáƒ–ებს
+Comment[kk]=NotePad файлдарының Ñақтық көшірмелерін жергілікті қапшықта жаÑау арнаÑÑ‹.
+Comment[km]=បំពង់​នáŸáŸ‡â€‹áž¢áž¶áž…​បម្រុង​ទុក​គំនូរ NotePad ទៅ​ážážâ€‹áž˜áž¼áž›ážŠáŸ’ឋាន ។
+Comment[lt]=Šis kanalas padaro NotePad piešinių atsargines kopijas į vietinį aplanką.
+Comment[ms]=Saluran ini menyandarkan lukisan NotePad ke folder setempat.
+Comment[nb]=Denne kanalen tar sikkerhetskopi av NotePad tegninger til en lokal mappe.
+Comment[nds]=Sekert NotePad-Teken binnen en lokaal Orner.
+Comment[ne]=यो कनà¥à¤¡à¥à¤¯à¥à¤Ÿà¤²à¥‡ सà¥à¤¥à¤¾à¤¨à¥€à¤¯ फाइलमा नोटपà¥à¤¯à¤¾à¤¡ रेखाचितà¥à¤° बà¥à¤¯à¤¾à¤•à¤…प गरà¥à¤› ।
+Comment[nl]=Dit conduit maakt een backup van de notitie-aantekeningen naar een lokale map.
+Comment[pl]=Ten łącznik robi kopię zapasową rysunków z Notatnika do lokalnego katalogu.
+Comment[pt]=Esta conduta salvaguarda desenhos NotePad para uma pasta local.
+Comment[pt_BR]=Este conduíte faz backup de desenhos do NotePad em uma pasta local.
+Comment[ru]=Канал ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ñ€ÐµÐ·ÐµÑ€Ð²Ð½Ñ‹Ñ… копий примечаний в локальной папке.
+Comment[sk]=Táto spojka zálohuje poznámky NotePad do lokálneho prieÄinku.
+Comment[sl]=Ta veznik arhivira risanja z NotePadom v krajevno mapo.
+Comment[sr]=Овај провод прави резервне копије NotePad цртежа у локалну фаÑциклу.
+Comment[sr@Latn]=Ovaj provod pravi rezervne kopije NotePad crteža u lokalnu fasciklu.
+Comment[sv]=Den här kanalen säkerhetskopierar ritade anteckningar i en lokal katalog.
+Comment[ta]=இத௠நோடà¯à®ªà¯‡à®Ÿà®¿à®©à¯ வரைபடஙà¯à®•à®³à¯ˆ உளà¯à®³à®Ÿà¯ˆà®µà¯à®•à¯à®•à¯ சேமிகà¯à®•à®¿à®±à®¤à¯
+Comment[tr]=Bu bileşen, NotePad çizimlerini yerel bir dosyaya aktarır veya alır.
+Comment[uk]=Цей акведук Ñтворює резервну копію нотаток у локальній теці.
+Comment[zh_CN]=此管é“将记事本的绘图ä¿å­˜åˆ°æœ¬åœ°æ–‡ä»¶å¤¹ã€‚
+Comment[zh_TW]=此軟體備份 NotePad 畫的圖到本地端資料夾。
+Implemented=file
+ServiceTypes=KPilotConduit
+X-KDE-Library=conduit_notepad
diff --git a/kpilot/conduits/notepadconduit/notepad-conduit.h b/kpilot/conduits/notepadconduit/notepad-conduit.h
new file mode 100644
index 000000000..5ba915e31
--- /dev/null
+++ b/kpilot/conduits/notepadconduit/notepad-conduit.h
@@ -0,0 +1,94 @@
+#ifndef _KPILOT_NOTEPAD_CONDUIT_H
+#define _KPILOT_NOTEPAD_CONDUIT_H
+/* notepad-conduit.h KPilot
+**
+** Copyright (C) 2004 by Adriaan de Groot, Joern Ahrens, Angus Ainslie
+**
+** The code for NotepadActionThread::unpackNotePad was taken from
+** Angus Ainslies read-notepad.c, which is part of pilot-link.
+** NotepadActionThread::saveImage is also based on read-notepad.c.
+**
+** This file is part of the Notepad conduit, a conduit for KPilot that
+** store the notepad drawings to files.
+*/
+
+/*
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU Lesser General Public License as published by
+** the Free Software Foundation; either version 2.1 of the License, or
+** (at your option) any later version.
+**
+** This 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 Lesser General Public License for more details.
+**
+** You should have received a copy of the GNU Lesser General Public License
+** along with this program in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include "plugin.h"
+
+#include <qthread.h>
+struct NotePad;
+class NotepadActionThread;
+
+class NotepadConduit : public ConduitAction
+{
+public:
+ NotepadConduit(KPilotLink *,
+ const char *name=0L,
+ const QStringList &args = QStringList());
+ virtual ~NotepadConduit();
+ virtual bool event(QEvent *e);
+
+protected:
+ virtual bool exec(); // From ConduitAction
+
+private:
+ NotepadActionThread *thread;
+};
+
+
+/**
+ * This class saves the notepads to disk
+ */
+class NotepadActionThread : public QThread
+{
+public:
+ NotepadActionThread(QObject *parent, KPilotLink *link);
+
+ virtual void run();
+ int getFailed() { return notSaved; }
+ int getSaved() { return saved; }
+
+private:
+ QObject *fParent;
+ KPilotLink *fLink;
+
+ /**
+ * counts how many notepads couldn't be saved during the sync
+ */
+ int notSaved;
+ /**
+ * counts how many files a saved during the sync
+ */
+ int saved;
+
+ int unpackNotePad(struct NotePad *a, unsigned char *buffer, int len);
+
+ /**
+ * Saves a single NotePad structure to disk, using the name in
+ * the Note @p n, or if no name is specified, using the
+ * timestamp in the note.
+ */
+ void saveImage(struct NotePad *n);
+};
+
+#endif
diff --git a/kpilot/conduits/notepadconduit/notepad-factory.cc b/kpilot/conduits/notepadconduit/notepad-factory.cc
new file mode 100644
index 000000000..f934a2cb1
--- /dev/null
+++ b/kpilot/conduits/notepadconduit/notepad-factory.cc
@@ -0,0 +1,124 @@
+/* KPilot
+**
+** Copyright (C) 2004 by Adriaan de Groot, Joern Ahrens
+**
+** This file defines the factory for the notepad-conduit plugin.
+*/
+
+/*
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU Lesser General Public License as published by
+** the Free Software Foundation; either version 2.1 of the License, or
+** (at your option) any later version.
+**
+** This 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 Lesser General Public License for more details.
+**
+** You should have received a copy of the GNU Lesser General Public License
+** along with this program in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include "options.h"
+
+#include <kconfig.h>
+#include <kinstance.h>
+#include <kaboutdata.h>
+#include <kurlrequester.h>
+#include <kmessagebox.h>
+#include <qlineedit.h>
+
+#include "pluginfactory.h"
+
+#include "notepad-conduit.h" // Conduit action
+#include "notepad-setup.h"
+#include "notepadconduit.h" // Settings class
+
+//----------------------------------------------------------------------------
+// Conduit Configuration
+//----------------------------------------------------------------------------
+class NotepadConduitConfig : public ConduitConfigBase
+{
+public:
+ NotepadConduitConfig(QWidget *parent=0L, const char *n=0L);
+ virtual void commit();
+ virtual void load();
+ static ConduitConfigBase *create(QWidget *p, const char *n)
+ {
+ return new NotepadConduitConfig(p, n);
+ };
+
+protected:
+ NotepadWidget *fConfigWidget;
+} ;
+
+static KAboutData *createAbout()
+{
+ FUNCTIONSETUP;
+
+ KAboutData *fAbout = new KAboutData("NotepadConduit",
+ I18N_NOOP("Saves notepads to png files"),
+ KPILOT_VERSION,
+ I18N_NOOP("Configures the Notepad Conduit for KPilot"),
+ KAboutData::License_LGPL,
+ "(C) 2004, Joern Ahrens");
+ fAbout->addAuthor("Joern Ahrens",
+ I18N_NOOP("Primary Author"),
+ "kde@jokele.de",
+ "http://www.jokele.de/");
+ fAbout->addCredit("Adriaan de Groot");
+ fAbout->addCredit("Angus Ainslies",
+ I18N_NOOP("Notepad conduit is based on Angus' read-notepad, part of pilot-link" ));
+ return fAbout;
+}
+
+
+NotepadConduitConfig::NotepadConduitConfig(QWidget *p, const char *n) :
+ ConduitConfigBase(p, n),
+ fConfigWidget(new NotepadWidget(p))
+{
+ FUNCTIONSETUP;
+
+ fConduitName = i18n("Notepad");
+ ConduitConfigBase::addAboutPage(fConfigWidget->tabWidget, createAbout());
+ fWidget=fConfigWidget;
+ QObject::connect(fConfigWidget->fOutputDirectory, SIGNAL(textChanged(const QString&)),
+ this, SLOT(modified()));
+ fConfigWidget->fOutputDirectory->setMode(KFile::Directory |
+ KFile::LocalOnly);
+}
+
+/* virtual */ void NotepadConduitConfig::commit()
+{
+ FUNCTIONSETUP;
+
+ NotepadConduitSettings::setOutputDirectory(fConfigWidget->fOutputDirectory->url());
+ NotepadConduitSettings::self()->writeConfig();
+}
+
+/* virtual */ void NotepadConduitConfig::load()
+{
+ FUNCTIONSETUP;
+
+ NotepadConduitSettings::self()->readConfig();
+ fConfigWidget->fOutputDirectory->setURL(NotepadConduitSettings::outputDirectory());
+ fModified=false;
+}
+
+extern "C"
+{
+
+void *init_conduit_notepad()
+{
+ return new ConduitFactory<NotepadConduitConfig,NotepadConduit>(0,"abbrowserconduit");
+}
+
+}
+
diff --git a/kpilot/conduits/notepadconduit/notepad-factory.h b/kpilot/conduits/notepadconduit/notepad-factory.h
new file mode 100644
index 000000000..f208cd1fe
--- /dev/null
+++ b/kpilot/conduits/notepadconduit/notepad-factory.h
@@ -0,0 +1,38 @@
+#ifndef _KPILOT_NOTEPAD_FACTORY_H
+#define _KPILOT_NOTEPAD_FACTORY_H
+/* notepad-factory.h KPilot
+**
+** Copyright (C) 2004 by Adriaan de Groot, Joern Ahrens
+**
+** This file defines the factory for the notepad-conduit plugin.
+*/
+
+/*
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU Lesser General Public License as published by
+** the Free Software Foundation; either version 2.1 of the License, or
+** (at your option) any later version.
+**
+** This 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 Lesser General Public License for more details.
+**
+** You should have received a copy of the GNU Lesser General Public License
+** along with this program in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+extern "C"
+{
+
+void *init_conduit_notepad();
+
+}
+
+#endif
diff --git a/kpilot/conduits/notepadconduit/notepad-setup.ui b/kpilot/conduits/notepadconduit/notepad-setup.ui
new file mode 100644
index 000000000..ccc3feb28
--- /dev/null
+++ b/kpilot/conduits/notepadconduit/notepad-setup.ui
@@ -0,0 +1,79 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>NotepadWidget</class>
+<author>Jörn Ahrens</author>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>Form2</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>435</width>
+ <height>391</height>
+ </rect>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Path to the directory to which the pictures should be exported.</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QTabWidget" row="0" column="0">
+ <property name="name">
+ <cstring>tabWidget</cstring>
+ </property>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>General</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer row="2" column="1">
+ <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>250</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="KURLRequester" row="1" column="1">
+ <property name="name">
+ <cstring>fOutputDirectory</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Output:</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </widget>
+ </grid>
+</widget>
+<layoutdefaults spacing="6" margin="11"/>
+<includes>
+ <include location="global" impldecl="in implementation">kurlrequester.h</include>
+ <include location="global" impldecl="in implementation">klineedit.h</include>
+ <include location="global" impldecl="in implementation">kpushbutton.h</include>
+</includes>
+</UI>
diff --git a/kpilot/conduits/notepadconduit/notepadconduit.kcfg b/kpilot/conduits/notepadconduit/notepadconduit.kcfg
new file mode 100644
index 000000000..1a2c9bf6f
--- /dev/null
+++ b/kpilot/conduits/notepadconduit/notepadconduit.kcfg
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
+ http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
+ <kcfgfile name="kpilotrc"/>
+ <group name="Notepad-conduit">
+ <entry name="outputDirectory" type="Path">
+ <label>The export directory for the notepad drawings</label>
+ <default>$HOME</default>
+ </entry>
+ </group>
+
+</kcfg>
diff --git a/kpilot/conduits/notepadconduit/notepadconduit.kcfgc b/kpilot/conduits/notepadconduit/notepadconduit.kcfgc
new file mode 100644
index 000000000..e18fa7c0c
--- /dev/null
+++ b/kpilot/conduits/notepadconduit/notepadconduit.kcfgc
@@ -0,0 +1,7 @@
+File=notepadconduit.kcfg
+ClassName=NotepadConduitSettings
+Singleton=true
+ItemAccessors=true
+Mutators=true
+GlobalEnums=true
+SetUserTexts=true
diff --git a/kpilot/conduits/null/CMakeLists.txt b/kpilot/conduits/null/CMakeLists.txt
new file mode 100644
index 000000000..b2fdbb8ad
--- /dev/null
+++ b/kpilot/conduits/null/CMakeLists.txt
@@ -0,0 +1,38 @@
+include_directories(
+ ${CMAKE_CURRENT_BINARY_DIR}
+)
+
+set(conduit_null_SRCS
+ null-conduit.cc
+ null-factory.cc
+)
+
+set(conduit_null_UIS
+ setup_base.ui
+)
+
+set(conduit_null_KCFGS
+ nullSettings.kcfgc
+)
+
+kde3_add_kcfg_files(conduit_null_SRCS ${conduit_null_KCFGS})
+kde3_add_ui_files(conduit_null_SRCS ${conduit_null_UIS})
+kde3_automoc(${conduit_null_SRCS})
+add_library(conduit_null SHARED ${conduit_null_SRCS})
+
+set_target_properties(
+ conduit_null PROPERTIES LOCATION ${KDE3_PLUGIN_INSTALL_DIR}
+ INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/lib
+ PREFIX ""
+)
+
+kde3_install_libtool_file(conduit_null)
+
+install(
+ TARGETS conduit_null
+ LIBRARY DESTINATION ${KDE3_PLUGIN_INSTALL_DIR}
+)
+
+install(
+ FILES null-conduit.desktop DESTINATION ${KDE3_SERVICES_DIR}
+)
diff --git a/kpilot/conduits/null/Makefile.am b/kpilot/conduits/null/Makefile.am
new file mode 100644
index 000000000..c1057b4df
--- /dev/null
+++ b/kpilot/conduits/null/Makefile.am
@@ -0,0 +1,15 @@
+INCLUDES= $(PISOCK_INCLUDE) -I$(top_srcdir)/kpilot/lib $(all_includes)
+
+METASOURCES = AUTO
+
+servicedir = $(kde_servicesdir)
+service_DATA = null-conduit.desktop
+
+kde_module_LTLIBRARIES = conduit_null.la
+
+
+conduit_null_la_SOURCES = nullSettings.kcfgc setup_base.ui null-conduit.cc null-factory.cc
+conduit_null_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries)
+conduit_null_la_LIBADD = ../../lib/libkpilot.la $(LIB_KDEUI)
+
+kde_kcfg_DATA = nullconduit.kcfg
diff --git a/kpilot/conduits/null/null-conduit.cc b/kpilot/conduits/null/null-conduit.cc
new file mode 100644
index 000000000..56599fec9
--- /dev/null
+++ b/kpilot/conduits/null/null-conduit.cc
@@ -0,0 +1,98 @@
+/* KPilot
+**
+** Copyright (C) 2000-2001 by Adriaan de Groot
+**
+** This file is part of the NULL conduit, a conduit for KPilot that
+** does nothing except add a log message to the Pilot's HotSync log.
+** It is also intended as a programming example.
+**
+** This file does the actual conduit work.
+*/
+
+/*
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU Lesser General Public License as published by
+** the Free Software Foundation; either version 2.1 of the License, or
+** (at your option) any later version.
+**
+** This 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 Lesser General Public License for more details.
+**
+** You should have received a copy of the GNU Lesser General Public License
+** along with this program in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+
+#include "options.h"
+
+// Only include what we really need:
+// First UNIX system stuff, then std C++,
+// then Qt, then KDE, then local includes.
+//
+//
+#include <time.h>
+
+#include <kconfig.h>
+#include <kdebug.h>
+
+#include "pilotSerialDatabase.h"
+#include "null-factory.h"
+#include "null-conduit.h"
+#include "nullSettings.h"
+
+// A conduit that does nothing has a very
+// simple constructor and destructor.
+//
+//
+NullConduit::NullConduit(KPilotLink *d,
+ const char *n,
+ const QStringList &l) :
+ ConduitAction(d,n,l),
+ fDatabase(0L),
+ fFailImmediately( l.contains( CSL1("--fail") ))
+{
+ FUNCTIONSETUP;
+ fConduitName=i18n("Null");
+}
+
+NullConduit::~NullConduit()
+{
+ FUNCTIONSETUP;
+ KPILOT_DELETE(fDatabase);
+}
+
+/* virtual */ bool NullConduit::exec()
+{
+ FUNCTIONSETUP;
+
+ DEBUGKPILOT << fname << ": Mode " << syncMode().name() << endl;
+
+ if ( fFailImmediately )
+ {
+ DEBUGKPILOT << fname << ": Config says to fail now." << endl;
+ emit logError(i18n("NULL conduit is programmed to fail."));
+ return false;
+ }
+
+ QString m(NullConduitSettings::logMessage());
+ if (!m.isEmpty())
+ {
+ addSyncLogEntry(m);
+ }
+
+ DEBUGKPILOT << fname
+ << ": Message from null-conduit: "
+ << m
+ << endl;
+
+ emit syncDone(this);
+ return true;
+}
diff --git a/kpilot/conduits/null/null-conduit.desktop b/kpilot/conduits/null/null-conduit.desktop
new file mode 100644
index 000000000..1a0c225dc
--- /dev/null
+++ b/kpilot/conduits/null/null-conduit.desktop
@@ -0,0 +1,64 @@
+[Desktop Entry]
+Type=Service
+Name=NULL
+Name[ca]=NUL
+Name[fa]=پوچ
+Name[mk]=Ðулов
+Name[ro]=NUL
+Name[sk]=NIČ
+Name[ta]=வெறà¯à®±à¯ மதிபà¯à®ªà¯
+Name[tr]=BOÅž
+Comment=This conduit does nothing.
+Comment[af]=Hierdie pad doen niks
+Comment[bg]=Това нещо прави нищо
+Comment[bs]=Ovaj conduit ne radi ništa.
+Comment[ca]=Aquest conducte no fa res.
+Comment[cs]=Toto propojení nedělá nic.
+Comment[cy]=Nid yw'r cwndid yma yn gwneud unrhyw beth.
+Comment[da]=Denne kanal gør ingenting.
+Comment[de]=Diese Erweiterung (Conduit) ist ohne Funktion
+Comment[el]=Αυτός ο σÏνδεσμος δεν κάνει τίποτα.
+Comment[eo]=Tiu kanalo faras nenion.
+Comment[et]=See kanal ei tee mitte kui midagi.
+Comment[eu]=Kanal honek ez du ezer egiten.
+Comment[fa]=این لوله هیچ چیز ندارد.
+Comment[fi]=Tämä yhdyskäytävä ei tee mitään.
+Comment[fr]=Ce canal ne fait rien.
+Comment[fy]=Dit conduit docht neat.
+Comment[ga]=Ní dhéanann an seoladán seo faic.
+Comment[gl]=Este conducto non fai nada.
+Comment[hi]=यह कनà¥à¤¡à¥à¤¯à¥‚इट कà¥à¤› नहीं करता है.
+Comment[hu]=Ez a csatoló üres, csak tesztelési célokat szolgál
+Comment[is]=Þessi rás gerir ekki neitt.
+Comment[it]=Questo conduit non fa nulla.
+Comment[ja]=ã“ã®ã‚³ãƒ³ã‚¸ãƒƒãƒˆã¯æœªçŸ¥ã§ã™ã€‚
+Comment[ka]=ეს áƒáƒ áƒ®áƒ˜ áƒáƒ áƒáƒ¤áƒ”რს áƒáƒ  áƒáƒ™áƒ”თებს.
+Comment[kk]=Ештеңе Ñ–Ñтемейтін арна.
+Comment[km]=បំពង់​នáŸáŸ‡â€‹áž˜áž·áž“​ធ្វើ​អ្វី​ទាំងអស់ ។
+Comment[lt]=Å is kanalas nieko neatlieka.
+Comment[mk]=Овој канал не прави ништо.
+Comment[ms]=Saluran ini tidak berbuat apa-apa.
+Comment[nb]=Denne kanalen gjør ingenting.
+Comment[nds]=Disse Kanaal deit gor nix.
+Comment[ne]=यो कनà¥à¤¡à¥à¤¯à¥à¤Ÿà¤²à¥‡ केही पनि गरà¥à¤¦à¥ˆà¤¨ ।
+Comment[nl]=Dit conduit doet niets.
+Comment[nn]=Denne koplinga gjer ingenting.
+Comment[pl]=Ten Å‚Ä…cznik nic nie robi.
+Comment[pt]=Esta conduta não faz nada.
+Comment[pt_BR]=Este conduíte não faz coisa alguma.
+Comment[ro]=Această conductă nu face nimic.
+Comment[ru]=Канал, который ничего не делает.
+Comment[sk]=Táto spojka niÄ nerobí.
+Comment[sl]=Ta veznik ne poÄne niÄesar.
+Comment[sr]=Овај провод не ради ништа.
+Comment[sr@Latn]=Ovaj provod ne radi ništa.
+Comment[sv]=Den här kanalen gör ingenting.
+Comment[ta]=இநà¯à®¤ காபà¯à®ªà¯à®•à¯ கà¯à®´à®¾à®¯à¯ ஒனà¯à®±à¯à®®à¯ செயà¯à®¯à®¾à®¤à¯
+Comment[tg]=Канале, ки дар ҳолати шурӯъ неÑÑ‚.
+Comment[tr]=Bu kanal herhangi bir iÅŸlem yapmaz.
+Comment[uk]=Цей акведук нічого не робить.
+Comment[zh_CN]=此管é“ä¸åšä»»ä½•äº‹ã€‚
+Comment[zh_TW]=ä¸åšä»»ä½•äº‹ã€‚
+Implemented=file
+ServiceTypes=KPilotConduit
+X-KDE-Library=conduit_null
diff --git a/kpilot/conduits/null/null-conduit.h b/kpilot/conduits/null/null-conduit.h
new file mode 100644
index 000000000..7bf1b67de
--- /dev/null
+++ b/kpilot/conduits/null/null-conduit.h
@@ -0,0 +1,65 @@
+#ifndef _NULL_NULL_CONDUIT_H
+#define _NULL_NULL_CONDUIT_H
+/* null-conduit.h KPilot
+**
+** Copyright (C) 2000-2001 by Adriaan de Groot
+**
+** This file is part of the NULL conduit, a conduit for KPilot that
+** does nothing except add a log message to the Pilot's HotSync log.
+** It is also intended as a programming example.
+*/
+
+/*
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU Lesser General Public License as published by
+** the Free Software Foundation; either version 2.1 of the License, or
+** (at your option) any later version.
+**
+** This 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 Lesser General Public License for more details.
+**
+** You should have received a copy of the GNU Lesser General Public License
+** along with this program in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include "plugin.h"
+
+class PilotRecord;
+class PilotDatabase;
+
+/**
+ * The conduit Null does nothing. Almost nothing, anyway.
+ * It writes a single log message to the sync log and then
+ * completes successfully. For debugging purposes it can
+ * also simulate failure, but that is a very specialized
+ * case available only programmatically.
+ */
+class NullConduit : public ConduitAction
+{
+public:
+ /** Constructor. Special case is if @p contains
+ * @c --fail as an argument to the conduit, then
+ * the conduit will fail instead of trivially succeeding.
+ */
+ NullConduit(KPilotLink *,
+ const char *name=0L,
+ const QStringList &args = QStringList());
+ virtual ~NullConduit();
+
+protected:
+ virtual bool exec();
+
+protected:
+ PilotDatabase *fDatabase;
+ bool fFailImmediately;
+};
+
+#endif
diff --git a/kpilot/conduits/null/null-factory.cc b/kpilot/conduits/null/null-factory.cc
new file mode 100644
index 000000000..2a829c6e3
--- /dev/null
+++ b/kpilot/conduits/null/null-factory.cc
@@ -0,0 +1,125 @@
+/* KPilot
+**
+** Copyright (C) 2001 by Dan Pilone
+**
+** This file defines the factory for the null-conduit plugin.
+*/
+
+/*
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU Lesser General Public License as published by
+** the Free Software Foundation; either version 2.1 of the License, or
+** (at your option) any later version.
+**
+** This 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 Lesser General Public License for more details.
+**
+** You should have received a copy of the GNU Lesser General Public License
+** along with this program in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include "options.h"
+
+#include <qtabwidget.h>
+#include <qlineedit.h>
+#include <qcheckbox.h>
+
+#include <kconfig.h>
+#include <kinstance.h>
+#include <kaboutdata.h>
+
+#include "pluginfactory.h"
+
+#include "setup_base.h"
+#include "null-conduit.h"
+#include "null-factory.h"
+#include "nullSettings.h"
+
+
+class NullConduitConfig : public ConduitConfigBase
+{
+public:
+ NullConduitConfig(QWidget *parent=0L, const char *n=0L);
+ virtual void commit();
+ virtual void load();
+protected:
+ NullWidget *fConfigWidget;
+ KAboutData *fAbout;
+} ;
+
+NullConduitConfig::NullConduitConfig(QWidget *p, const char *n) :
+ ConduitConfigBase(p,n),
+ fConfigWidget(new NullWidget(p))
+{
+ FUNCTIONSETUP;
+ fConduitName = i18n("Null");
+ fAbout = new KAboutData("nullConduit",
+ I18N_NOOP("Null Conduit for KPilot"),
+ KPILOT_VERSION,
+ I18N_NOOP("Configures the Null Conduit for KPilot"),
+ KAboutData::License_GPL,
+ "(C) 2001, Adriaan de Groot");
+ fAbout->addAuthor("Adriaan de Groot",
+ I18N_NOOP("Primary Author"),
+ "groot@kde.org",
+ "http://www.cs.kun.nl/~adridg/kpilot");
+
+ ConduitConfigBase::addAboutPage(fConfigWidget->tabWidget,fAbout);
+ fWidget=fConfigWidget;
+ QObject::connect(fConfigWidget->fLogMessage,SIGNAL(textChanged(const QString&)),
+ this,SLOT(modified()));
+}
+
+/* virtual */ void NullConduitConfig::commit()
+{
+ FUNCTIONSETUP;
+
+#ifdef DEBUG
+ DEBUGKPILOT << fname
+ << ": Message="
+ << fConfigWidget->fLogMessage->text()
+ << endl;
+#endif
+
+ NullConduitSettings::setLogMessage( fConfigWidget->fLogMessage->text() );
+ NullConduitSettings::self()->writeConfig();
+ unmodified();
+}
+
+/* virtual */ void NullConduitConfig::load()
+{
+ FUNCTIONSETUP;
+ NullConduitSettings::self()->readConfig();
+
+ fConfigWidget->fLogMessage->setText( NullConduitSettings::logMessage() );
+#ifdef DEBUG
+ DEBUGKPILOT << fname
+ << ": Read Message="
+ << fConfigWidget->fLogMessage->text()
+ << endl;
+#endif
+
+ unmodified();
+}
+
+
+
+extern "C"
+{
+
+unsigned long version_conduit_null = Pilot::PLUGIN_API;
+void *init_conduit_null()
+{
+ return new ConduitFactory<NullConduitConfig,NullConduit>(0,"nullconduit");
+}
+
+}
+
diff --git a/kpilot/conduits/null/null-factory.h b/kpilot/conduits/null/null-factory.h
new file mode 100644
index 000000000..2897ad4f8
--- /dev/null
+++ b/kpilot/conduits/null/null-factory.h
@@ -0,0 +1,40 @@
+#ifndef _KPILOT_NULL_FACTORY_H
+#define _KPILOT_NULL_FACTORY_H
+/* null-factory.h KPilot
+**
+** Copyright (C) 2001 by Dan Pilone
+**
+** This file defines the factory for the null-conduit plugin.
+** It also defines the class for the behavior of the setup dialog.
+*/
+
+/*
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU Lesser General Public License as published by
+** the Free Software Foundation; either version 2.1 of the License, or
+** (at your option) any later version.
+**
+** This 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 Lesser General Public License for more details.
+**
+** You should have received a copy of the GNU Lesser General Public License
+** along with this program in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+
+extern "C"
+{
+
+void *init_conduit_null();
+
+}
+
+#endif
diff --git a/kpilot/conduits/null/nullSettings.kcfgc b/kpilot/conduits/null/nullSettings.kcfgc
new file mode 100644
index 000000000..17a65cade
--- /dev/null
+++ b/kpilot/conduits/null/nullSettings.kcfgc
@@ -0,0 +1,7 @@
+File=nullconduit.kcfg
+ClassName= NullConduitSettings
+Singleton=true
+ItemAccessors=true
+Mutators=true
+GlobalEnums=true
+SetUserTexts=true
diff --git a/kpilot/conduits/null/nullconduit.kcfg b/kpilot/conduits/null/nullconduit.kcfg
new file mode 100644
index 000000000..3e899f1ad
--- /dev/null
+++ b/kpilot/conduits/null/nullconduit.kcfg
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
+ http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
+ <kcfgfile name="kpilotrc"/>
+ <group name="Null-conduit">
+ <entry name="LogMessage" type="String">
+ <label>The error message if the null conduit is supposed to fail</label>
+ <default>KPilot was here.</default>
+ </entry>
+ </group>
+</kcfg>
diff --git a/kpilot/conduits/null/setup_base.ui b/kpilot/conduits/null/setup_base.ui
new file mode 100644
index 000000000..7e0d02ee9
--- /dev/null
+++ b/kpilot/conduits/null/setup_base.ui
@@ -0,0 +1,128 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>NullWidget</class>
+<comment>A tabWidget for configuring
+the Null-conduit settings.</comment>
+<author>Adriaan de Groot</author>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>Form1</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>342</width>
+ <height>163</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="baseSize">
+ <size>
+ <width>570</width>
+ <height>270</height>
+ </size>
+ </property>
+ <property name="caption">
+ <string>Null-Conduit Options</string>
+ </property>
+ <property name="layoutMargin" stdset="0">
+ </property>
+ <property name="layoutSpacing" stdset="0">
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QTabWidget" row="0" column="0">
+ <property name="name">
+ <cstring>tabWidget</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="layoutMargin" stdset="0">
+ </property>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>Widget2</cstring>
+ </property>
+ <attribute name="title">
+ <string>General</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLineEdit" row="0" column="1">
+ <property name="name">
+ <cstring>fLogMessage</cstring>
+ </property>
+ <property name="text">
+ <string>KPilot was here.</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Enter the message to add to the Sync Log on your Pilot here.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>TextLabel1_2</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Log message:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>fLogMessage</cstring>
+ </property>
+ </widget>
+ <spacer row="3" column="1">
+ <property name="name">
+ <cstring>Spacer4</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>
+ </grid>
+ </widget>
+ </widget>
+ </grid>
+</widget>
+<tabstops>
+ <tabstop>tabWidget</tabstop>
+</tabstops>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/kpilot/conduits/popmail/CMakeLists.txt b/kpilot/conduits/popmail/CMakeLists.txt
new file mode 100644
index 000000000..daec3c3a8
--- /dev/null
+++ b/kpilot/conduits/popmail/CMakeLists.txt
@@ -0,0 +1,43 @@
+include_directories(
+ ${CMAKE_CURRENT_BINARY_DIR}
+)
+
+set(conduit_popmail_SRCS
+ popmail-factory.cc
+ popmail-conduit.cc
+ setupDialog.cc
+)
+
+set(conduit_popmail_UIS
+ setup-dialog.ui
+)
+
+set(conduit_popmail_KCFGS
+ popmailSettings.kcfgc
+)
+
+kde3_add_kcfg_files(conduit_popmail_SRCS ${conduit_popmail_KCFGS})
+kde3_add_ui_files(conduit_popmail_SRCS ${conduit_popmail_UIS})
+kde3_automoc(${conduit_popmail_SRCS})
+add_library(conduit_popmail SHARED ${conduit_popmail_SRCS})
+
+set_target_properties(
+ conduit_popmail PROPERTIES LOCATION ${KDE3_PLUGIN_INSTALL_DIR}
+ INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/lib
+ PREFIX ""
+)
+
+kde3_install_libtool_file(conduit_popmail)
+
+install(
+ TARGETS conduit_popmail
+ LIBRARY DESTINATION ${KDE3_PLUGIN_INSTALL_DIR}
+)
+
+install(
+ FILES popmail-conduit.desktop DESTINATION ${KDE3_SERVICES_DIR}
+)
+
+install(
+ FILES popmail.kcfg DESTINATION ${KDE3_KCFG_DIR}
+)
diff --git a/kpilot/conduits/popmail/Makefile.am b/kpilot/conduits/popmail/Makefile.am
new file mode 100644
index 000000000..0e565805d
--- /dev/null
+++ b/kpilot/conduits/popmail/Makefile.am
@@ -0,0 +1,24 @@
+### Makefile for the popmail conduit
+###
+
+INCLUDES= $(PISOCK_INCLUDE) -I$(top_srcdir)/kpilot/lib $(all_includes)
+METASOURCES = AUTO
+
+servicedir = $(kde_servicesdir)
+service_DATA = popmail-conduit.desktop
+kde_kcfg_DATA = popmail.kcfg
+
+####### This part is very kpilot specific
+# you can add here more. This one gets installed
+kde_module_LTLIBRARIES = conduit_popmail.la
+
+# Which sources should be compiled for popmail_conduit
+conduit_popmail_la_SOURCES = popmailSettings.kcfgc setup-dialog.ui \
+ popmail-factory.cc setupDialog.cc \
+ popmail-conduit.cc
+conduit_popmail_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries)
+conduit_popmail_la_LIBADD = ../../lib/libkpilot.la $(LIB_KIO)
+
+# this option you can leave out. Just, if you use "make dist", you need it
+noinst_HEADERS = popmail-conduit.h setupDialog.h
+
diff --git a/kpilot/conduits/popmail/popmail-conduit.cc b/kpilot/conduits/popmail/popmail-conduit.cc
new file mode 100644
index 000000000..47315edaa
--- /dev/null
+++ b/kpilot/conduits/popmail/popmail-conduit.cc
@@ -0,0 +1,416 @@
+/* KPilot
+**
+** Copyright (C) 1998-2001 Dan Pilone
+** Copyright (C) 1999,2000 Michael Kropfberger
+**
+** This file is part of the popmail conduit, a conduit for KPilot that
+** synchronises the Pilot's email application with the outside world,
+** which currently means:
+** -- sendmail or SMTP for outgoing mail
+** -- POP or mbox for incoming mail
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include "options.h"
+#include "popmail-conduit.h"
+
+extern "C"
+{
+
+unsigned long version_conduit_popmail = Pilot::PLUGIN_API;
+
+}
+
+#include <qsocket.h>
+#include <qregexp.h>
+
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/utsname.h>
+#include <ctype.h>
+
+#include <unistd.h>
+#include <errno.h>
+
+#include <time.h> // Needed by pilot-link include
+#include <pi-version.h>
+#if PILOT_LINK_MAJOR < 10
+#include <pi-config.h>
+#endif
+#include <pi-mail.h>
+
+#include <qdir.h>
+#include <qtextstream.h>
+#include <qtextcodec.h>
+
+#include <kapplication.h>
+#include <kmessagebox.h>
+#include <ksock.h>
+#include <kconfig.h>
+#include <ksimpleconfig.h>
+#include <dcopclient.h>
+#include <ktempfile.h>
+
+#include "pilotRecord.h"
+#include "pilotSerialDatabase.h"
+
+#include "popmailSettings.h"
+#include "setupDialog.h"
+
+static QString DATE_FORMAT("ddd, d MMM yyyy hh:mm:ss");
+
+PopMailConduit::PopMailConduit(KPilotLink *d,
+ const char *n,
+ const QStringList &l) :
+ ConduitAction(d,n,l)
+{
+ FUNCTIONSETUP;
+ fConduitName=i18n("KMail");
+}
+
+PopMailConduit::~PopMailConduit()
+{
+ FUNCTIONSETUP;
+}
+
+void PopMailConduit::doSync()
+{
+ FUNCTIONSETUP;
+
+ int sent_count=0;
+ int mode=MailConduitSettings::syncOutgoing();
+
+ DEBUGKPILOT << fname
+ << ": Outgoing mail disposition "
+ << mode << endl;
+
+ if(mode)
+ {
+ sent_count=sendPendingMail(mode);
+ }
+
+ if (sent_count>0)
+ {
+ if (sent_count>0)
+ {
+ addSyncLogEntry(i18n("Sent one message",
+ "Sent %n messages",sent_count));
+ }
+ }
+}
+
+
+// additional changes by Michael Kropfberger
+int PopMailConduit::sendPendingMail(int mode)
+{
+ FUNCTIONSETUP;
+ int count=0;
+
+ if (mode==PopMailWidgetConfig::SendKMail)
+ {
+ count=sendViaKMail();
+ }
+
+ if (count == 0)
+ {
+ WARNINGKPILOT << "Mail was not sent at all!" << endl;
+ emit logError(i18n("No mail was sent."));
+ }
+ else if (count < 0)
+ {
+ WARNINGKPILOT
+ << "Mail sending returned error " << count
+ << endl;
+ emit logError(i18n("No mail could be sent."));
+ }
+ else
+ {
+ DEBUGKPILOT << fname
+ << ": Sent "
+ << count
+ << " messages"
+ << endl;
+ }
+
+ return count;
+}
+
+
+QString PopMailConduit::getKMailOutbox() const
+{
+ FUNCTIONSETUP;
+
+ // Default to "outbox" with newer KMails.
+ KSimpleConfig c(CSL1("kmailrc"),true);
+ c.setGroup("General");
+
+ QString outbox = c.readEntry("outboxFolder");
+ if (outbox.isEmpty())
+ {
+ outbox = MailConduitSettings::outboxFolder();
+ }
+
+ if (outbox.isEmpty()) outbox=CSL1("outbox");
+
+ return outbox;
+}
+
+/*
+ * This function uses KMail's DCOP interface to put all the
+ * outgoing mail into the outbox.
+ */
+int PopMailConduit::sendViaKMail()
+{
+ FUNCTIONSETUP;
+ int count=0;
+ QString kmailOutboxName = getKMailOutbox();
+
+ DCOPClient *dcopptr = KApplication::kApplication()->dcopClient();
+ if (!dcopptr)
+ {
+ WARNINGKPILOT << "Cannot get DCOP client."
+ << endl;
+ KMessageBox::error(0L,
+ i18n("Could not connect to DCOP server for "
+ "the KMail connection."),
+ i18n("Error Sending Mail"));
+ return -1;
+ }
+
+ if (!dcopptr->isAttached())
+ {
+ dcopptr->attach();
+ }
+
+ while (PilotRecord *pilotRec = fDatabase->readNextRecInCategory(1))
+ {
+ DEBUGKPILOT << fname
+ << ": Reading "
+ << count + 1
+ << "th message"
+ << endl;
+
+ if (pilotRec->isDeleted() || pilotRec->isArchived())
+ {
+ DEBUGKPILOT << fname
+ << ": Skipping record."
+ << endl;
+ continue;
+ }
+
+ struct Mail theMail;
+ KTempFile t;
+ t.setAutoDelete(true);
+
+ if (t.status())
+ {
+ WARNINGKPILOT << "Cannot open temp file." << endl;
+ KMessageBox::error(0L,
+ i18n("Cannot open temporary file to store "
+ "mail from Pilot in."),
+ i18n("Error Sending Mail"));
+ continue;
+ }
+
+ FILE *sendf = t.fstream();
+
+ if (!sendf)
+ {
+ WARNINGKPILOT
+ << "Cannot open temporary file for writing!" << endl;
+ KMessageBox::error(0L,
+ i18n("Cannot open temporary file to store "
+ "mail from Pilot in."),
+ i18n("Error Sending Mail"));
+ continue;
+ }
+
+ unpack_Mail(&theMail,
+ (unsigned char*)pilotRec->data(),
+ pilotRec->size());
+ writeMessageToFile(sendf, theMail);
+
+
+ QByteArray data,returnValue;
+ QCString returnType;
+ QDataStream arg(data,IO_WriteOnly);
+
+ arg << kmailOutboxName << t.name() << CSL1("N") ;
+
+ if (!dcopptr->call("kmail",
+ "KMailIface",
+ "dcopAddMessage(QString,QString,QString)",
+ data,
+ returnType,
+ returnValue,
+ true))
+ {
+ WARNINGKPILOT << "DCOP call failed." << endl;
+
+ KMessageBox::error(0L,
+ i18n("DCOP connection with KMail failed."),
+ i18n("Error Sending Mail"));
+ continue;
+ }
+
+ DEBUGKPILOT << fname
+ << ": DCOP call returned "
+ << returnType
+ << " of "
+ << (const char *)returnValue
+ << endl;
+
+ // Mark it as filed...
+ pilotRec->setCategory(3);
+ pilotRec->setModified( false );
+ fDatabase->writeRecord(pilotRec);
+ delete pilotRec;
+ // This is ok since we got the mail with unpack mail..
+ free_Mail(&theMail);
+
+ count++;
+ }
+
+ return count;
+}
+
+// From pilot-link-0.8.7 by Kenneth Albanowski
+// additional changes by Michael Kropfberger
+
+void PopMailConduit::writeMessageToFile(FILE* sendf, struct Mail& theMail)
+{
+ FUNCTIONSETUP;
+
+ QTextStream mailPipe(sendf, IO_WriteOnly);
+
+ QString fromAddress = MailConduitSettings::emailAddress();
+ mailPipe << "From: " << fromAddress << "\r\n";
+ mailPipe << "To: " << theMail.to << "\r\n";
+ if(theMail.cc)
+ mailPipe << "Cc: " << theMail.cc << "\r\n";
+ if(theMail.bcc)
+ mailPipe << "Bcc: " << theMail.bcc << "\r\n";
+ if(theMail.replyTo)
+ mailPipe << "Reply-To: " << theMail.replyTo << "\r\n";
+ if(theMail.subject)
+ mailPipe << "Subject: " << theMail.subject << "\r\n";
+
+ // if our struct indicates that it's dated, then use the date it
+ // holds. otherwise, provide current date. either way, we need to
+ // have a date...
+ QDateTime date = QDateTime::currentDateTime();
+ if (theMail.dated)
+ {
+ date = readTm(theMail.date);
+ }
+
+ QString dateString = date.toString(DATE_FORMAT);
+
+ mailPipe << "Date: " << dateString << "\r\n";
+
+ mailPipe << "X-mailer: " << "Popmail-Conduit " << KPILOT_VERSION << "\r\n";
+ mailPipe << "\r\n";
+
+
+ DEBUGKPILOT << fname << ": To: " << theMail.to << endl;
+
+
+ if(theMail.body)
+ {
+ DEBUGKPILOT << fname << ": Sent body." << endl;
+ mailPipe << theMail.body << "\r\n";
+ }
+
+ //insert the real signature file from disk
+ QString signature = MailConduitSettings::signature();
+ if(!signature.isEmpty())
+ {
+ DEBUGKPILOT << fname << ": Reading signature" << endl;
+
+ QFile f(signature);
+ if ( f.open(IO_ReadOnly) )
+ { // file opened successfully
+ mailPipe << "-- \r\n";
+ QTextStream t( &f ); // use a text stream
+ while ( !t.eof() )
+ { // until end of file...
+ mailPipe << t.readLine() << "\r\n";
+ }
+ f.close();
+ }
+ }
+ mailPipe << "\r\n";
+
+ DEBUGKPILOT << fname << ": Done" << endl;
+}
+
+
+/* virtual */ void PopMailConduit::doTest()
+{
+ FUNCTIONSETUP;
+
+ QString outbox = getKMailOutbox();
+
+ DEBUGKPILOT << fname
+ << ": KMail's outbox is "
+ << outbox
+ << endl;
+
+ QDateTime date = QDateTime::currentDateTime();
+ QString dateString = date.toString(DATE_FORMAT);
+
+ DEBUGKPILOT << fname << ": Date format example: [" << dateString
+ << "]" << endl;
+}
+
+/* virtual */ bool PopMailConduit::exec()
+{
+ FUNCTIONSETUP;
+
+ if (syncMode().isTest())
+ {
+ doTest();
+ }
+ else if (syncMode() == SyncMode::eBackup)
+ {
+ emit logError(i18n("Cannot perform backup of mail database"));
+ }
+ else
+ {
+ fDatabase = deviceLink()->database( CSL1("MailDB") );
+
+ if (!fDatabase || !fDatabase->isOpen())
+ {
+ emit logError(i18n("Unable to open mail database on handheld"));
+ KPILOT_DELETE(fDatabase);
+ return false;
+ }
+
+ doSync();
+ fDatabase->resetSyncFlags();
+ KPILOT_DELETE(fDatabase);
+ }
+ delayDone();
+ return true;
+}
diff --git a/kpilot/conduits/popmail/popmail-conduit.desktop b/kpilot/conduits/popmail/popmail-conduit.desktop
new file mode 100644
index 000000000..b4cdc0175
--- /dev/null
+++ b/kpilot/conduits/popmail/popmail-conduit.desktop
@@ -0,0 +1,109 @@
+[Desktop Entry]
+Type=Service
+Comment=Send mail from your handheld through KMail.
+Comment[af]=Stuur pos vanaf jou draagbare toestel deur KMail.
+Comment[bg]=Изпращане на поща от мобилно уÑтройÑтво чрез KMail.
+Comment[ca]=Envia correu des de la vostra agenda electrònica a través de KMail.
+Comment[cs]=Odeslání zprávy z PDA přes KMail.
+Comment[da]=Send post fra din håndholdte gennem KMail.
+Comment[de]=Zum Versenden von E-Mails mit dem Taschencomputer via KMail.
+Comment[el]=Αποστολή αλληλογÏαφίας από τον υπολογιστή παλάμης σας μέσω του KMail.
+Comment[eo]=Sendu poÅton de via poÅkomputilo per KMail.
+Comment[es]=Envía el correo de la agenda electrónica a través de KMail.
+Comment[et]=Saadab pihuseadmest KMaili vahendusel e-kirja.
+Comment[eu]=Bidali posta zure agenda elektronikotik KMail-en bidez.
+Comment[fa]=ارسال نامه از طریق KMail، از دستی شما.
+Comment[fi]=Lähetä sähköpostia taskutietokoneelta KMailin kautta.
+Comment[fr]=Permet d'envoyer des messages du Palm vers KMail
+Comment[fy]=Dit conduit ferstjoerd e-post fan jo handheld mei help fan KMail.
+Comment[gl]=Enviar correo dende o seu aparello de man a través de KMail.
+Comment[hu]=Ezzel a csatolóval kézi számítógépről lehet levelet küldeni a KMailen keresztül.
+Comment[is]=Sendu tölvupóst frá lófatölvunni þinni gegnum KMail.
+Comment[it]=Invia la posta dal tuo palmare tramite KMail.
+Comment[ja]=KMail 経由ã§ãƒãƒ³ãƒ‰ãƒ˜ãƒ«ãƒ‰ã‹ã‚‰ãƒ¡ãƒ¼ãƒ«ã‚’é€ä¿¡ã—ã¾ã™ã€‚
+Comment[ka]= ფáƒáƒ¡áƒ¢áƒ˜áƒ¡ გáƒáƒ’ზáƒáƒ•áƒœáƒ პáƒáƒ áƒ¢áƒáƒ¢áƒ˜áƒ£áƒšáƒ˜ მáƒáƒ¬áƒ§áƒáƒ‘ილáƒáƒ‘იდáƒáƒœ KMail-ის სáƒáƒ¨áƒ£áƒáƒšáƒ”ბით.
+Comment[kk]=Қалта құрылғының поштаÑын KMail арқылы жіберу.
+Comment[km]=ផ្ញើ​សំបុážáŸ’រ​ទៅ​ឧបករណáŸâ€‹áž™áž½ážšážŠáŸƒâ€‹ážšáž”ស់​អ្នក​ážáž¶áž˜â€‹ážšáž™áŸˆ KMail ។
+Comment[lt]=Siųsti paštą iš nešiojamo įrenginio per KMail.
+Comment[ms]=Menghantar mel dari komputer telapak melalui KMail.
+Comment[nb]=Send e-post fra PDA-en gjennom KMail.
+Comment[nds]=Nettbreven vun Dien Handreekner över KMail afsennen
+Comment[ne]=तपाईà¤à¤•à¥‹ हà¥à¤¯à¤¾à¤¨à¥à¤¡à¤¹à¥‡à¤²à¥à¤¡à¤¬à¤¾à¤Ÿ केडीई मेलहà¥à¤¦à¥ˆ पतà¥à¤° पठाउनà¥à¤¹à¥‹à¤¸à¥ ।
+Comment[nl]=Dit conduit verzendt mail van uw handheld met behulp van KMail.
+Comment[pl]=Wysyła pocztę z palmtopa za pomocą KMail.
+Comment[pt]=Enviar e-mail do seu dispositivo móvel através do KMail.
+Comment[pt_BR]=Envia e-mail do seu handheld através do Kmail.
+Comment[ru]=Отправка почты Ñ ÐšÐŸÐš через KMail.
+Comment[sk]=Pošle poštu z prenosného zariadenia cez KMail.
+Comment[sl]=PoÅ¡ljite poÅ¡to z vaÅ¡ega roÄnega raÄunalnika preko KMaila.
+Comment[sr]=Пошаљите пошту Ñа вашег ручног рачунара кроз KMail.
+Comment[sr@Latn]=PoÅ¡aljite poÅ¡tu sa vaÅ¡eg ruÄnog raÄunara kroz KMail.
+Comment[sv]=Skicka e-post från handdatorn via Kmail.
+Comment[ta]=இநà¯à®¤ காபà¯à®ªà¯à®•à¯à®•à¯à®´à®¾à®¯à¯ உஙà¯à®•à®³à¯ கையேடà¯à®Ÿà®¿à®²à¯ இரà¯à®¨à¯à®¤à¯ தேதி பà¯à®¤à¯à®¤à®•à®¤à¯à®¤à¯ˆ கேஅமைபாளரà¯à®•à¯à®•à¯ ஒதà¯à®¤à®¿à®šà¯ˆà®•à¯à®•à®¿à®±à®¤à¯
+Comment[tr]=El bilgisayarınızdan KMail aracılığı ile e-posta gönderir.
+Comment[uk]=ВідÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð¿Ð¾ÑˆÑ‚Ð¸ з кишенькового приÑтрою через KMail.
+Comment[zh_CN]=通过 KMail 从您的手æŒè®¾å¤‡å‘é€é‚®ä»¶ã€‚
+Comment[zh_TW]=é€éŽ KMail é€å‡ºæ‚¨ handheld 的信件。
+Name=Mail
+Name[af]=Pos
+Name[ar]=البريد
+Name[be]=Пошта
+Name[bg]=Поща
+Name[br]=Lizher
+Name[ca]=Correu
+Name[cs]=Pošta
+Name[cy]=Ebost
+Name[da]=Brev
+Name[de]=E-Mail
+Name[eo]=RetpoÅto
+Name[es]=Correo
+Name[et]=E-post
+Name[eu]=Posta
+Name[fa]=نامه
+Name[fi]=Sähköposti
+Name[fr]=Messages
+Name[fy]=E-post
+Name[ga]=Ríomhphost
+Name[gl]=Correo-e
+Name[he]=דו×"ל
+Name[hi]=डाक
+Name[hr]=Pošta
+Name[hu]=E-mail
+Name[is]=Póstur
+Name[it]=Posta
+Name[ja]=メール
+Name[ka]=ფáƒáƒ¡áƒ¢áƒ
+Name[kk]=Пошта
+Name[km]=សំបុážáŸ’ážš
+Name[lt]=Paštas
+Name[mk]=Е-пошта
+Name[ms]=Mel
+Name[nb]=E-post
+Name[nds]=Nettpost
+Name[ne]=पतà¥à¤°
+Name[nl]=E-mail
+Name[nn]=E-post
+Name[pa]=ਪੱਤਰ
+Name[pl]=Poczta
+Name[pt]=E-mail
+Name[pt_BR]=Correio
+Name[ro]=E-Mail
+Name[ru]=Почта
+Name[se]=E-boasta
+Name[sk]=Pošta
+Name[sl]=Pošta
+Name[sr]=Пошта
+Name[sr@Latn]=Pošta
+Name[sv]=Brev
+Name[ta]=அஞà¯à®šà®²à¯
+Name[tg]=Мактуб
+Name[th]=จดหมาย
+Name[tr]=Posta
+Name[uk]=Пошта
+Name[uz]=Xat-xabar
+Name[uz@cyrillic]=Хат-хабар
+Name[zh_CN]=邮件
+Name[zh_TW]=郵件
+Implemented=file
+ServiceTypes=KPilotConduit
+X-KDE-Library=conduit_popmail
diff --git a/kpilot/conduits/popmail/popmail-conduit.h b/kpilot/conduits/popmail/popmail-conduit.h
new file mode 100644
index 000000000..1df1a6912
--- /dev/null
+++ b/kpilot/conduits/popmail/popmail-conduit.h
@@ -0,0 +1,74 @@
+#ifndef _KPILOT_POPMAIL_CONDUIT_H
+#define _KPILOT_POPMAIL_CONDUIT_H
+/* popmail-conduit.h KPilot
+**
+** Copyright (C) 1998,1999,2000 Dan Pilone
+** Copyright (C) 1999,2000 Michael Kropfberger
+**
+** This file is part of the popmail conduit, a conduit for KPilot that
+** synchronises the Pilot's email application with the outside world,
+** which currently means:
+** -- sendmail or SMTP for outgoing mail
+** -- POP or mbox for incoming mail
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+
+#include "plugin.h"
+
+class KSocket;
+
+class PilotRecord;
+class PilotDatabase;
+
+class PopMailConduit : public ConduitAction
+{
+public:
+ PopMailConduit(KPilotLink *d,
+ const char *n=0L,
+ const QStringList &l=QStringList());
+ virtual ~PopMailConduit();
+
+protected:
+ virtual bool exec();
+
+ // static PilotRecord *readMessage(FILE *mailbox,
+ // char *buffer,int bufferSize);
+
+protected:
+ void doSync();
+ void doTest();
+
+ // Pilot -> Sendmail
+ //
+ //
+ int sendPendingMail(int mode /* unused */);
+ // int sendViaSendmail();
+ int sendViaKMail();
+ // int sendViaSMTP();
+ void writeMessageToFile(FILE* sendf, struct Mail& theMail);
+ QString getKMailOutbox() const;
+
+};
+
+#endif
diff --git a/kpilot/conduits/popmail/popmail-factory.cc b/kpilot/conduits/popmail/popmail-factory.cc
new file mode 100644
index 000000000..dc2a0cd13
--- /dev/null
+++ b/kpilot/conduits/popmail/popmail-factory.cc
@@ -0,0 +1,47 @@
+/* KPilot
+**
+** Copyright (C) 2001 by Dan Pilone
+** Copyright (C) 2006 by Adriaan de Groot <groot@kde.org>
+**
+** This file defines the factory for the popmail-conduit plugin.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include "options.h"
+
+
+#include "setupDialog.h"
+#include "popmail-conduit.h"
+#include "pluginfactory.h"
+
+
+extern "C"
+{
+
+void *init_conduit_popmail()
+{
+ return new ConduitFactory<PopMailWidgetConfig,PopMailConduit>;
+}
+
+}
+
diff --git a/kpilot/conduits/popmail/popmail-factory.h b/kpilot/conduits/popmail/popmail-factory.h
new file mode 100644
index 000000000..2cab4d840
--- /dev/null
+++ b/kpilot/conduits/popmail/popmail-factory.h
@@ -0,0 +1,37 @@
+#ifndef _KPILOT_POPMAIL_FACTORY_H
+#define _KPILOT_POPMAIL_FACTORY_H
+/* popmail-factory.h KPilot
+**
+** Copyright (C) 2001 by Dan Pilone
+**
+** This file defines the factory for the popmail-conduit plugin.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+
+extern "C"
+{
+void *init_conduit_popmail();
+}
+
+#endif
diff --git a/kpilot/conduits/popmail/popmail.kcfg b/kpilot/conduits/popmail/popmail.kcfg
new file mode 100644
index 000000000..65056cb56
--- /dev/null
+++ b/kpilot/conduits/popmail/popmail.kcfg
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
+ http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
+<kcfgfile name="kpilot_mailconduitrc"/>
+<group name="General">
+ <entry name="SyncOutgoing" type="UInt">
+ <label>Selects the way in which mail is sent: none (0), kmail (1).</label>
+ <default>0</default>
+ </entry>
+ <entry name="EmailAddress" type="String">
+ <label>The email address entered in the To: field of outgoing messages.</label>
+ <default></default>
+ </entry>
+ <entry name="Signature" type="Path">
+ <label>The pathname of your .signature file.</label>
+ <default>$HOME/.signature</default>
+ </entry>
+ <entry name="OutboxFolder" type="String">
+ <label>The name of KMail's outbox - use with caution.</label>
+ <default></default>
+ </entry>
+</group>
+</kcfg>
diff --git a/kpilot/conduits/popmail/popmailSettings.kcfgc b/kpilot/conduits/popmail/popmailSettings.kcfgc
new file mode 100644
index 000000000..1ac6276fc
--- /dev/null
+++ b/kpilot/conduits/popmail/popmailSettings.kcfgc
@@ -0,0 +1,7 @@
+File=popmail.kcfg
+ClassName=MailConduitSettings
+Singleton=true
+ItemAccessors=true
+Mutators=true
+GlobalEnums=true
+SetUserTexts=true
diff --git a/kpilot/conduits/popmail/setup-dialog.ui b/kpilot/conduits/popmail/setup-dialog.ui
new file mode 100644
index 000000000..e10f0e4b8
--- /dev/null
+++ b/kpilot/conduits/popmail/setup-dialog.ui
@@ -0,0 +1,141 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>PopMailWidget</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>PopMailWidget</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>363</width>
+ <height>281</height>
+ </rect>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QTabWidget" row="0" column="0">
+ <property name="name">
+ <cstring>fTabWidget</cstring>
+ </property>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Send Mail</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer row="5" column="1">
+ <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>16</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel1_2</cstring>
+ </property>
+ <property name="text">
+ <string>Send method:</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Select the method KPilot will use to send the mail from your Handheld to the recipients here. Depending on the method you choose, the other fields in the dialog may be enabled or disabled. Currently, the only &lt;i&gt;working&lt;/i&gt; method is through KMail.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Email address:</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Enter the email address you want to send messages as here.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="KLineEdit" row="1" column="1">
+ <property name="name">
+ <cstring>fEmailFrom</cstring>
+ </property>
+ <property name="text">
+ <string>$USER</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Enter the email address you want to send messages as here.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="2" column="0">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Signature file:</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;If you want to add a signature file, enter the location of your signature file (usually, &lt;i&gt;.signature&lt;/i&gt;, located in your home folder) here, or select it clicking the file picker button. The signature file contains the text that is added to the end of your outgoing mail messages.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="KURLRequester" row="2" column="1">
+ <property name="name">
+ <cstring>fSignature</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;If you want to add a signature file, enter the location of your signature file (usually, &lt;i&gt;.signature&lt;/i&gt;, located in your home folder) here, or select it clicking the file picker button. The signature file contains the text that is added to the end of your outgoing mail messages.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QComboBox" row="0" column="1">
+ <item>
+ <property name="text">
+ <string>Do Not Send Mail</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Use KMail</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>fSendMode</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Select the method KPilot will use to send the mail from your Handheld to the recipients here. Depending on the method you choose, the other fields in the dialog may be enabled or disabled. Currently, the only &lt;i&gt;working&lt;/i&gt; method is through KMail.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </widget>
+ </grid>
+</widget>
+<layoutdefaults spacing="6" margin="11"/>
+<includes>
+ <include location="global" impldecl="in implementation">klineedit.h</include>
+ <include location="global" impldecl="in implementation">kurlrequester.h</include>
+ <include location="global" impldecl="in implementation">kpushbutton.h</include>
+</includes>
+</UI>
diff --git a/kpilot/conduits/popmail/setupDialog.cc b/kpilot/conduits/popmail/setupDialog.cc
new file mode 100644
index 000000000..64553562b
--- /dev/null
+++ b/kpilot/conduits/popmail/setupDialog.cc
@@ -0,0 +1,158 @@
+/* KPilot
+**
+** Copyright (C) 1998-2001 Dan Pilone
+**
+** This file is part of the popmail conduit, a conduit for KPilot that
+** synchronises the Pilot's email application with the outside world,
+** which currently means:
+** -- sendmail or SMTP for outgoing mail
+** -- POP or mbox for incoming mail
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include "options.h"
+
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+
+#include <kconfig.h>
+#include <kstandarddirs.h>
+#include <klineedit.h>
+#include <kaboutdata.h>
+
+#include <qcheckbox.h>
+#include <qdir.h>
+#include <qcombobox.h>
+
+#include "kfiledialog.h"
+
+#include <kurlrequester.h>
+
+
+#include "popmail-factory.h"
+#include "setup-dialog.h"
+#include "setupDialog.moc"
+#include "popmailSettings.h"
+
+
+
+PopMailWidgetConfig::PopMailWidgetConfig(QWidget *p,const char *n) :
+ ConduitConfigBase(p,n),
+ fConfigWidget(new PopMailWidget(p,"PopMailWidget"))
+{
+ FUNCTIONSETUP;
+ fConduitName = i18n("KMail");
+ KAboutData *fAbout = new KAboutData("popmailConduit",
+ I18N_NOOP("Mail Conduit for KPilot"),
+ KPILOT_VERSION,
+ I18N_NOOP("Configures the Mail Conduit for KPilot"),
+ KAboutData::License_GPL,
+ "(C) 2001, Dan Pilone, Michael Kropfberger, Adriaan de Groot");
+ fAbout->addAuthor("Adriaan de Groot",
+ I18N_NOOP("Maintainer"),
+ "groot@kde.org",
+ "http://www.kpilot.org/");
+ fAbout->addAuthor("Dan Pilone",
+ I18N_NOOP("Original Author"));
+ fAbout->addCredit("Michael Kropfberger",
+ I18N_NOOP("POP3 code"));
+ fAbout->addCredit("Marko Gr&ouml;nroos",
+ I18N_NOOP("SMTP support and redesign"),
+ "magi@iki.fi",
+ "http://www.iki.fi/magi/");
+
+ ConduitConfigBase::addAboutPage(fConfigWidget->fTabWidget,fAbout);
+ fWidget=fConfigWidget;
+
+#define CM(a,b) connect(fConfigWidget->a,b,this,SLOT(modified()));
+ CM(fSendMode,SIGNAL(activated(int)));
+ CM(fEmailFrom,SIGNAL(textChanged(const QString &)));
+ CM(fSignature,SIGNAL(textChanged(const QString &)));
+#undef CM
+
+ connect(fConfigWidget->fSendMode,SIGNAL(activated(int)),
+ this,SLOT(toggleSendMode(int)));
+
+}
+
+void PopMailWidgetConfig::commit()
+{
+ FUNCTIONSETUP;
+
+ MailConduitSettings::self()->readConfig();
+#define WR(a,b,c) MailConduitSettings::set##a(fConfigWidget->b->c);
+ WR(SyncOutgoing,fSendMode,currentItem());
+ WR(EmailAddress,fEmailFrom,text());
+ WR(Signature,fSignature,url());
+#undef WR
+
+ MailConduitSettings::self()->writeConfig();
+ unmodified();
+}
+
+void PopMailWidgetConfig::load()
+{
+ FUNCTIONSETUP;
+ MailConduitSettings::self()->config()->sync();
+ MailConduitSettings::self()->readConfig();
+
+#define RD(a,b,c) fConfigWidget->a->b(MailConduitSettings::c())
+ RD(fSendMode,setCurrentItem,syncOutgoing);
+ RD(fEmailFrom,setText,emailAddress);
+ RD(fSignature,setURL,signature);
+#undef RD
+
+ toggleSendMode(fConfigWidget->fSendMode->currentItem());
+
+ MailConduitSettings::self()->writeConfig();
+ unmodified();
+}
+
+
+/* slot */ void PopMailWidgetConfig::toggleSendMode(int i)
+{
+ FUNCTIONSETUP;
+#ifdef DEBUG
+ DEBUGKPILOT << fname << ": Got mode " << i << endl;
+#endif
+
+#define E(a,b) fConfigWidget->a->setEnabled(b)
+ switch(i)
+ {
+ case SendKMail :
+ E(fEmailFrom,true);
+ E(fSignature,true);
+ break;
+ case NoSend : /* FALLTHRU */
+ default :
+ E(fEmailFrom,false);
+ E(fSignature,false);
+ break;
+ }
+#undef E
+}
+
+
+
diff --git a/kpilot/conduits/popmail/setupDialog.h b/kpilot/conduits/popmail/setupDialog.h
new file mode 100644
index 000000000..248b4ecbf
--- /dev/null
+++ b/kpilot/conduits/popmail/setupDialog.h
@@ -0,0 +1,62 @@
+#ifndef _POPMAIL_SETUPDIALOG_H
+#define _POPMAIL_SETUPDIALOG_H
+/* setupDialog.h KPilot
+**
+** Copyright (C) 1998-2001 Dan Pilone
+**
+** This file is part of the popmail conduit, a conduit for KPilot that
+** synchronises the Pilot's email application with the outside world,
+** which currently means:
+** -- sendmail or SMTP for outgoing mail
+** -- POP or mbox for incoming mail
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+
+#include "plugin.h"
+
+class PopMailWidget; // From setup-dialog.ui
+
+class PopMailWidgetConfig : public ConduitConfigBase
+{
+Q_OBJECT
+public:
+ PopMailWidgetConfig(QWidget *, const char *);
+ virtual void load();
+ virtual void commit();
+
+ static ConduitConfigBase *create(QWidget *w, const char *n)
+ { return new PopMailWidgetConfig(w,n); } ;
+
+ // These enums must follow the order of items in the combo box
+ enum SendMode { NoSend=0, SendKMail=1 } ;
+
+protected:
+ PopMailWidget *fConfigWidget;
+
+public slots:
+ void toggleSendMode(int);
+} ;
+
+
+#endif
diff --git a/kpilot/conduits/recordconduit/Makefile.am b/kpilot/conduits/recordconduit/Makefile.am
new file mode 100644
index 000000000..33ceb8540
--- /dev/null
+++ b/kpilot/conduits/recordconduit/Makefile.am
@@ -0,0 +1,15 @@
+INCLUDES= $(PISOCK_INCLUDE) -I$(top_srcdir)/kpilot/lib $(all_includes)
+
+METASOURCES = AUTO
+
+servicedir = $(kde_servicesdir)
+service_DATA = record-conduit.desktop
+
+kde_module_LTLIBRARIES = conduit_record.la
+
+
+conduit_record_la_SOURCES = settings.kcfgc setup_base.ui factory.cc
+conduit_record_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries)
+conduit_record_la_LIBADD = ../../lib/libkpilot.la $(LIB_KDEUI)
+
+kde_kcfg_DATA = settings.kcfg
diff --git a/kpilot/conduits/recordconduit/factory.cc b/kpilot/conduits/recordconduit/factory.cc
new file mode 100644
index 000000000..8015763d1
--- /dev/null
+++ b/kpilot/conduits/recordconduit/factory.cc
@@ -0,0 +1,144 @@
+/* KPilot
+**
+** Copyright (C) 2005 by Adriaan de Groot
+**
+** This file defines the factory for the recordconduit plugin.
+*/
+
+/*
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU Lesser General Public License as published by
+** the Free Software Foundation; either version 2.1 of the License, or
+** (at your option) any later version.
+**
+** This 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 Lesser General Public License for more details.
+**
+** You should have received a copy of the GNU Lesser General Public License
+** along with this program in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include "options.h"
+
+#include <qtabwidget.h>
+#include <qlineedit.h>
+#include <qcheckbox.h>
+
+#include <kconfig.h>
+#include <kinstance.h>
+#include <kaboutdata.h>
+
+#include "pluginfactory.h"
+#include "pilotDatabase.h"
+#include "recordConduit.h"
+
+#include "setup_base.h"
+#include "factory.h"
+#include "settings.h"
+
+
+class ConduitConfig : public ConduitConfigBase
+{
+public:
+ ConduitConfig(QWidget *parent=0L, const char *n=0L);
+ virtual void commit();
+ virtual void load();
+protected:
+ RecordWidget *fConfigWidget;
+ KAboutData *fAbout;
+} ;
+
+ConduitConfig::ConduitConfig(QWidget *p, const char *n) :
+ ConduitConfigBase(p,n),
+ fConfigWidget(new RecordWidget(p))
+{
+ FUNCTIONSETUP;
+ fConduitName = i18n("Record Conduit");
+ fAbout = new KAboutData("recordConduit",
+ I18N_NOOP("Record Conduit for KPilot"),
+ KPILOT_VERSION,
+ I18N_NOOP("Configures the Record Conduit for KPilot"),
+ KAboutData::License_GPL,
+ "(C) 2005, Adriaan de Groot");
+ fAbout->addAuthor("Adriaan de Groot",
+ I18N_NOOP("Primary Author"),
+ "groot@kde.org",
+ "http://people.fruitsalad.org/adridg/");
+
+ ConduitConfigBase::addAboutPage(fConfigWidget->tabWidget,fAbout);
+ fWidget=fConfigWidget;
+ QObject::connect(fConfigWidget->fLogMessage,SIGNAL(textChanged(const QString&)),
+ this,SLOT(modified()));
+ QObject::connect(fConfigWidget->fDatabases,SIGNAL(textChanged(const QString&)),
+ this,SLOT(modified()));
+ QObject::connect(fConfigWidget->fFailImmediately,SIGNAL(toggled(bool)),
+ this,SLOT(modified()));
+}
+
+/* virtual */ void ConduitConfig::commit()
+{
+ FUNCTIONSETUP;
+
+#ifdef DEBUG
+ DEBUGKPILOT << fname
+ << ": Message="
+ << fConfigWidget->fLogMessage->text()
+ << endl;
+ DEBUGKPILOT << fname
+ << ": Databases="
+ << fConfigWidget->fDatabases->text()
+ << endl;
+#endif
+
+ ConduitSettings::setLogMessage( fConfigWidget->fLogMessage->text() );
+ ConduitSettings::setDatabases( fConfigWidget->fDatabases->text() );
+ ConduitSettings::setFailImmediately( fConfigWidget->fFailImmediately->isChecked());
+ ConduitSettings::self()->writeConfig();
+ unmodified();
+}
+
+/* virtual */ void ConduitConfig::load()
+{
+ FUNCTIONSETUP;
+ ConduitSettings::self()->readConfig();
+
+ fConfigWidget->fLogMessage->setText( ConduitSettings::logMessage() );
+ fConfigWidget->fDatabases->setText( ConduitSettings::databases().join(",") );
+ fConfigWidget->fFailImmediately->setChecked( ConduitSettings::failImmediately() );
+
+#ifdef DEBUG
+ DEBUGKPILOT << fname
+ << ": Read Message="
+ << fConfigWidget->fLogMessage->text()
+ << endl;
+ DEBUGKPILOT << fname
+ << ": Read Database="
+ << fConfigWidget->fDatabases->text()
+ << endl;
+#endif
+
+ unmodified();
+}
+
+typedef PilotDatabase PilotDatabaseContainer;
+
+typedef RecordConduit<PilotRecord, PilotDatabaseContainer, PilotRecord, PilotAppInfoBase, NullMapper<PilotRecord> > RecordAction;
+
+extern "C"
+{
+
+void *init_conduit_record()
+{
+ return new ConduitFactory<ConduitConfig,RecordAction>(0,"recordconduit");
+}
+
+}
+
diff --git a/kpilot/conduits/recordconduit/factory.h b/kpilot/conduits/recordconduit/factory.h
new file mode 100644
index 000000000..6d35d4db1
--- /dev/null
+++ b/kpilot/conduits/recordconduit/factory.h
@@ -0,0 +1,40 @@
+#ifndef KPILOT_RECORD_FACTORY_H
+#define KPILOT_RECORD_FACTORY_H
+/* factory.h KPilot
+**
+** Copyright (C) 2005 by Adriaan de Groot
+**
+** This is the factory for the recordconduit, which uses the
+** template class RecordConduit for demonstration purposes.
+*/
+
+/*
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU Lesser General Public License as published by
+** the Free Software Foundation; either version 2.1 of the License, or
+** (at your option) any later version.
+**
+** This 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 Lesser General Public License for more details.
+**
+** You should have received a copy of the GNU Lesser General Public License
+** along with this program in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+
+extern "C"
+{
+
+void *init_conduit_record();
+
+}
+
+#endif
diff --git a/kpilot/conduits/recordconduit/record-conduit.desktop b/kpilot/conduits/recordconduit/record-conduit.desktop
new file mode 100644
index 000000000..55c953d17
--- /dev/null
+++ b/kpilot/conduits/recordconduit/record-conduit.desktop
@@ -0,0 +1,93 @@
+[Desktop Entry]
+Type=Service
+Name=Records (Experimental)
+Name[af]=Rekords (Eksperimenteel)
+Name[bg]=ЗапиÑи (ЕкÑпериментално)
+Name[ca]=Registres (Experimental)
+Name[cs]=Záznamy (experimentální)
+Name[da]=Indspilninger (eksperimentel)
+Name[de]=Einträge (Experimentell)
+Name[el]=ΕγγÏαφές (ΠειÏαματικό)
+Name[es]=Registros (Experimental)
+Name[et]=Kirjed (eksperimentaalne)
+Name[fr]=Enregistrements (expérimental)
+Name[fy]=Opnames (eksperimenteel)
+Name[gl]=Grava (Experimental)
+Name[hu]=Rekordok (kísérleti)
+Name[is]=Færslur (á tilraunastigi)
+Name[it]=Record (sperimentale)
+Name[ja]=レコード (実験中)
+Name[kk]=Жазулар (ЭкÑперименталдық)
+Name[km]=កំណážáŸ‹â€‹ážáŸ’រា (ពិសោធនáŸ)
+Name[lt]=Įrašai (eksperimentinis)
+Name[nb]=Records (Eksperimentell)
+Name[nds]=Logbook (warrt utprobeert)
+Name[ne]=रेकरà¥à¤¡ (पà¥à¤°à¤¯à¥‹à¤—ातà¥à¤®à¤•)
+Name[nl]=Opnames (experimenteel)
+Name[pl]=Wpisy (eksperymentalne)
+Name[pt]=Registos (Experimental)
+Name[pt_BR]=Registros (Experimental)
+Name[ru]=ЗапиÑи (ÑкÑпериментально)
+Name[sk]=Záznamy (Experimentálne)
+Name[sl]=Zapisi (poskusno)
+Name[sr]=Слогови (екÑпериментално)
+Name[sr@Latn]=Slogovi (eksperimentalno)
+Name[sv]=Inspelningar (experimentell)
+Name[tr]=Kayıtlar (Deneysel)
+Name[uk]=ЗапиÑи (екÑпериментальний)
+Name[zh_CN]=记录(试验性)
+Name[zh_TW]=紀錄(實驗性)
+Comment=This conduit does nothing.
+Comment[af]=Hierdie pad doen niks
+Comment[bg]=Това нещо прави нищо
+Comment[bs]=Ovaj conduit ne radi ništa.
+Comment[ca]=Aquest conducte no fa res.
+Comment[cs]=Toto propojení nedělá nic.
+Comment[cy]=Nid yw'r cwndid yma yn gwneud unrhyw beth.
+Comment[da]=Denne kanal gør ingenting.
+Comment[de]=Diese Erweiterung (Conduit) ist ohne Funktion
+Comment[el]=Αυτός ο σÏνδεσμος δεν κάνει τίποτα.
+Comment[eo]=Tiu kanalo faras nenion.
+Comment[et]=See kanal ei tee mitte kui midagi.
+Comment[eu]=Kanal honek ez du ezer egiten.
+Comment[fa]=این لوله هیچ چیز ندارد.
+Comment[fi]=Tämä yhdyskäytävä ei tee mitään.
+Comment[fr]=Ce canal ne fait rien.
+Comment[fy]=Dit conduit docht neat.
+Comment[ga]=Ní dhéanann an seoladán seo faic.
+Comment[gl]=Este conducto non fai nada.
+Comment[hi]=यह कनà¥à¤¡à¥à¤¯à¥‚इट कà¥à¤› नहीं करता है.
+Comment[hu]=Ez a csatoló üres, csak tesztelési célokat szolgál
+Comment[is]=Þessi rás gerir ekki neitt.
+Comment[it]=Questo conduit non fa nulla.
+Comment[ja]=ã“ã®ã‚³ãƒ³ã‚¸ãƒƒãƒˆã¯æœªçŸ¥ã§ã™ã€‚
+Comment[ka]=ეს áƒáƒ áƒ®áƒ˜ áƒáƒ áƒáƒ¤áƒ”რს áƒáƒ  áƒáƒ™áƒ”თებს.
+Comment[kk]=Ештеңе Ñ–Ñтемейтін арна.
+Comment[km]=បំពង់​នáŸáŸ‡â€‹áž˜áž·áž“​ធ្វើ​អ្វី​ទាំងអស់ ។
+Comment[lt]=Å is kanalas nieko neatlieka.
+Comment[mk]=Овој канал не прави ништо.
+Comment[ms]=Saluran ini tidak berbuat apa-apa.
+Comment[nb]=Denne kanalen gjør ingenting.
+Comment[nds]=Disse Kanaal deit gor nix.
+Comment[ne]=यो कनà¥à¤¡à¥à¤¯à¥à¤Ÿà¤²à¥‡ केही पनि गरà¥à¤¦à¥ˆà¤¨ ।
+Comment[nl]=Dit conduit doet niets.
+Comment[nn]=Denne koplinga gjer ingenting.
+Comment[pl]=Ten Å‚Ä…cznik nic nie robi.
+Comment[pt]=Esta conduta não faz nada.
+Comment[pt_BR]=Este conduíte não faz coisa alguma.
+Comment[ro]=Această conductă nu face nimic.
+Comment[ru]=Канал, который ничего не делает.
+Comment[sk]=Táto spojka niÄ nerobí.
+Comment[sl]=Ta veznik ne poÄne niÄesar.
+Comment[sr]=Овај провод не ради ништа.
+Comment[sr@Latn]=Ovaj provod ne radi ništa.
+Comment[sv]=Den här kanalen gör ingenting.
+Comment[ta]=இநà¯à®¤ காபà¯à®ªà¯à®•à¯ கà¯à®´à®¾à®¯à¯ ஒனà¯à®±à¯à®®à¯ செயà¯à®¯à®¾à®¤à¯
+Comment[tg]=Канале, ки дар ҳолати шурӯъ неÑÑ‚.
+Comment[tr]=Bu kanal herhangi bir iÅŸlem yapmaz.
+Comment[uk]=Цей акведук нічого не робить.
+Comment[zh_CN]=此管é“ä¸åšä»»ä½•äº‹ã€‚
+Comment[zh_TW]=ä¸åšä»»ä½•äº‹ã€‚
+Implemented=file
+ServiceTypes=KPilotConduit
+X-KDE-Library=conduit_record
diff --git a/kpilot/conduits/recordconduit/settings.kcfg b/kpilot/conduits/recordconduit/settings.kcfg
new file mode 100644
index 000000000..7fc2180df
--- /dev/null
+++ b/kpilot/conduits/recordconduit/settings.kcfg
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
+ http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
+ <kcfgfile name="kpilotrc"/>
+ <group name="RecordConduit">
+ <entry name="FailImmediately" key="FailNow" type="Bool">
+ <label>Whether the conduit should immediately bail out with an error</label>
+ <default>false</default>
+ </entry>
+ <entry name="LogMessage" type="String">
+ <label>The error message if the null conduit is supposed to fail</label>
+ <default>KPilot was here.</default>
+ </entry>
+ <entry name="Databases" type="StringList">
+ <label>Databases that are skipped on sync</label>
+ <default></default>
+ </entry>
+ </group>
+
+</kcfg>
diff --git a/kpilot/conduits/recordconduit/settings.kcfgc b/kpilot/conduits/recordconduit/settings.kcfgc
new file mode 100644
index 000000000..8a2b4f356
--- /dev/null
+++ b/kpilot/conduits/recordconduit/settings.kcfgc
@@ -0,0 +1,7 @@
+File=settings.kcfg
+ClassName= ConduitSettings
+Singleton=true
+ItemAccessors=true
+Mutators=true
+GlobalEnums=true
+SetUserTexts=true
diff --git a/kpilot/conduits/recordconduit/setup_base.ui b/kpilot/conduits/recordconduit/setup_base.ui
new file mode 100644
index 000000000..126d3ff20
--- /dev/null
+++ b/kpilot/conduits/recordconduit/setup_base.ui
@@ -0,0 +1,158 @@
+<!DOCTYPE UI><UI version="3.1" stdsetdef="1">
+<class>RecordWidget</class>
+<comment>A tabWidget for configuring
+the Record-conduit settings.</comment>
+<author>Adriaan de Groot</author>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>Form1</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>342</width>
+ <height>163</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="baseSize">
+ <size>
+ <width>570</width>
+ <height>270</height>
+ </size>
+ </property>
+ <property name="caption">
+ <string>Null-Conduit Options</string>
+ </property>
+ <property name="layoutMargin" stdset="0">
+ </property>
+ <property name="layoutSpacing" stdset="0">
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QTabWidget" row="0" column="0">
+ <property name="name">
+ <cstring>tabWidget</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="layoutMargin" stdset="0">
+ </property>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>Widget2</cstring>
+ </property>
+ <attribute name="title">
+ <string>General</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLineEdit" row="0" column="1">
+ <property name="name">
+ <cstring>fLogMessage</cstring>
+ </property>
+ <property name="text">
+ <string>KPilot was here.</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Enter the message to add to the Sync Log on your Pilot here.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>TextLabel1_2</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Log message:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>fLogMessage</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>TextLabel2_2</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Databases:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>fDatabases</cstring>
+ </property>
+ </widget>
+ <widget class="QLineEdit" row="1" column="1">
+ <property name="name">
+ <cstring>fDatabases</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;The Null-conduit can be attached to several databases, effectively preventing them from Syncing. Enter the database names here.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <spacer row="3" column="1">
+ <property name="name">
+ <cstring>Spacer4</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>
+ <widget class="QCheckBox" row="2" column="1">
+ <property name="name">
+ <cstring>fFailImmediately</cstring>
+ </property>
+ <property name="text">
+ <string>Simulate failure</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Force the conduit to simulate a failure to perform the HotSync.</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </widget>
+ </grid>
+</widget>
+<tabstops>
+ <tabstop>tabWidget</tabstop>
+</tabstops>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/kpilot/conduits/sysinfoconduit/CMakeLists.txt b/kpilot/conduits/sysinfoconduit/CMakeLists.txt
new file mode 100644
index 000000000..cae6d89f1
--- /dev/null
+++ b/kpilot/conduits/sysinfoconduit/CMakeLists.txt
@@ -0,0 +1,50 @@
+include_directories(
+ ${CMAKE_CURRENT_BINARY_DIR}
+)
+
+set(conduit_sysinfo_SRCS
+ sysinfo-setup.cc
+ sysinfo-factory.cc
+ sysinfo-conduit.cc
+)
+
+set(conduit_sysinfo_UIS
+ sysinfo-setup_dialog.ui
+)
+
+set(conduit_sysinfo_KCFGS
+ sysinfoSettings.kcfgc
+)
+
+kde3_add_kcfg_files(conduit_sysinfo_SRCS ${conduit_sysinfo_KCFGS})
+kde3_add_ui_files(conduit_sysinfo_SRCS ${conduit_sysinfo_UIS})
+kde3_automoc(${conduit_sysinfo_SRCS})
+add_library(conduit_sysinfo SHARED ${conduit_sysinfo_SRCS})
+
+set_target_properties(
+ conduit_sysinfo PROPERTIES LOCATION ${KDE3_PLUGIN_INSTALL_DIR}
+ INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/lib
+ PREFIX ""
+)
+
+kde3_install_libtool_file(conduit_sysinfo)
+
+install(
+ TARGETS conduit_sysinfo
+ LIBRARY DESTINATION ${KDE3_PLUGIN_INSTALL_DIR}
+)
+
+install(
+ FILES sysinfo_conduit.desktop DESTINATION ${KDE3_SERVICES_DIR}
+)
+
+install(
+ FILES sysinfoSettings.kcfgc sysinfoconduit.kcfg
+ DESTINATION ${KDE3_KCFG_DIR}
+)
+
+install(
+ FILES Template.html Template.txt
+ DESTINATION ${CMAKE_INSTALL_PREFIX}/share/apps/kpilot/sysinfoconduit
+)
+
diff --git a/kpilot/conduits/sysinfoconduit/Makefile.am b/kpilot/conduits/sysinfoconduit/Makefile.am
new file mode 100644
index 000000000..eb7f7aa92
--- /dev/null
+++ b/kpilot/conduits/sysinfoconduit/Makefile.am
@@ -0,0 +1,24 @@
+### Makefile for the sysinfo conduit
+###
+### The sysinfo conduit is Copyright (C) 2003 by Reinhold Kainhofer
+
+INCLUDES= $(PISOCK_INCLUDE) -I$(top_srcdir)/kpilot/lib $(all_includes)
+METASOURCES = AUTO
+
+servicedir = $(kde_servicesdir)
+service_DATA = sysinfo_conduit.desktop
+
+kde_module_LTLIBRARIES = conduit_sysinfo.la
+
+conduit_sysinfo_la_SOURCES = sysinfoSettings.kcfgc \
+ sysinfo-factory.cc \
+ sysinfo-setup.cc \
+ sysinfo-conduit.cc \
+ sysinfo-setup_dialog.ui
+conduit_sysinfo_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries)
+conduit_sysinfo_la_LIBADD = ../../lib/libkpilot.la $(LIB_KDEUI) $(LIB_KIO)
+
+kpilot_sysinfo_data_DATA = Template.html Template.txt
+kpilot_sysinfo_datadir = $(kde_datadir)/kpilot/sysinfoconduit
+EXTRA_DIST = $(kpilot_sysinfo_data_DATA)
+kde_kcfg_DATA = sysinfoconduit.kcfg
diff --git a/kpilot/conduits/sysinfoconduit/Template.html b/kpilot/conduits/sysinfoconduit/Template.html
new file mode 100644
index 000000000..e5a33e0fd
--- /dev/null
+++ b/kpilot/conduits/sysinfoconduit/Template.html
@@ -0,0 +1,184 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<head>
+ <title>KPilot System Information Page</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-15">
+ <meta name="GENERATOR" content="KPilot SysInfo conduit">
+ <style type="text/css">
+ h1 {
+ font-family: sans-serif;
+ font-size: xx-large;
+ font-style: italic;
+ font-variant: small-caps;
+ font-weight: bolder;
+ color: darkBlue;
+ border-bottom: thick solid darkBlue;
+ margin: 30;
+ }
+ h2 {
+ font-family: sans-serif;
+ font-size: large;
+ color: darkRed;
+ margin-top: 40;
+ border-top: thin solid darkRed;
+ display: list-item;
+ list-style-type: circle;
+ margin: 40;
+ }
+ th {
+ font-style: italic;
+ font-weight: bold;
+ background-color: #DFC370;
+ text-align: center;
+ }
+ </style>
+</head>
+<body bgcolor="#FFE080">
+ <h1>KPilot System Information</h1>
+ <center>
+<p><!--#ifhardware#<a href="#Hardware">Hardware info</a> - #endifhardware#-->
+<!--#ifuser#<a href="#User">User info</a> - #endifuser#-->
+<!--#ifmemory#<a href="#Memory">Memory info</a> - #endifmemory#-->
+<!--#ifstorage#<a href="#Storage">Storage info</a> - #endifstorage#-->
+<!--#ifdblist#<a href="#DBList">Database list</a> - #endifdblist#-->
+<!--#ifrecords#<a href="#Records">Addresses, to-dos, events, and memos</a> - #endifrecords#-->
+<!--#ifsync#<a href="#Sync">Sync info</a> - #endifsync#-->
+<!--#ifpcversion#<a href="#Version">PC Version info</a> - #endifpcversion#-->
+<!--#ifpalmversion#<a href="#PalmVersion">Palm Version info</a> - #endifpalmversion#-->
+<!--#ifdebug#<a href="#Debug">Debug info</a>#endifdebug#--></p>
+ </center>
+
+
+<!--#ifhardware#<h2><a name="Hardware">Hardware Information</a></h2>
+ <center>
+ <table border=1>
+ <tbody>
+ <tr><td><b>DeviceID:</b></td><td>#deviceid#</td></tr>
+ <tr><td><b>Device name:</b></td><td>#devicename#</td></tr>
+ <tr><td><b>Device model:</b></td><td>#devicemodel#</td></tr>
+ <tr><td><b>Manufacturer:</b></td><td>#manufacturer#</td></tr>
+ <tr><td><b>Connected via:</b></td><td>#devicetype#</td></tr>
+ </tbody>
+ </table>
+ </center>#endifhardware#-->
+
+
+<!--#ifuser#<h2><a name="User">User Information</a></h2>
+ <center>
+ <table border=1>
+ <tbody>
+ <tr><td><b>Handheld User Name:</b></td><td>#username#</td></tr>
+ <tr><td><b>Handheld Password:</b></td><td>#pw#</td></tr>
+ <tr><td><b>Handheld User ID:</b></td><td>#uid#</td></tr>
+ <tr><td><b>Viewer ID:</b></td><td>#viewerid#</td></tr>
+ </tbody>
+ </table>
+ </center>#endifuser#-->
+
+
+<!--#ifmemory#<h2><a name="Memory">Memory Information</a></h2>
+ <center>
+ <table border=1>
+ <tbody>
+ <tr><td><b>ROM:</b></td><td>#rom# kB total</td></tr>
+ <tr><td><b>Total RAM:</b></td><td>#totalmem# kB total</td></tr>
+ <tr><td><b>Free RAM:</b></td><td>#freemem# kB free</td></tr>
+ </tbody>
+ </table>
+ </center>#endifmemory#-->
+
+
+<!--#ifstorage#<h2><a name="Storage">Storage Information</a></h2>
+ <center>
+ <table border=1>
+ <tbody>
+ <tr><td><b>Cards:</b></td><td>#cards#</td></tr>
+ </tbody>
+ </table>
+ </center>#endifstorage#-->
+
+
+<!--#ifdblist#<h2><a name="DBList">List of Databases on Handheld</a></h2>
+ <center>
+ <table border=1>
+ <tr><th>DB name</th><th>type, creator</th><th>index</th><th>flags</th>
+ <th>created</th><th>modified</th><th>version</th></tr>
+ #dblist[<tr><td>%0</td><td>%1,%2</td><td>%3</td><td>%4/%5</td>
+ <td>%7</td><td>%8</td><td>%6</td></tr>
+ ]#
+ </table>
+ </center>#endifdblist#-->
+
+
+
+<!--#ifrecords#<h2><a name="Records">Number of addresses, to-dos, events, and memos</a></h2>
+ <center>
+ <table border=1>
+ <thead>
+ <tr><th scope=col>Record type</th><th scope=col># of recs</th></tr>
+ </thead>
+ <tbody>
+ <tr><td><b>Addresses:</b></td><td>#addresses# entries in Addressbook</td></tr>
+ <tr><td><b>Events:</b></td><td>#events# entries in Calendar</td></tr>
+ <tr><td><b>To-dos:</b></td><td>#todos# entries in To-do list</td></tr>
+ <tr><td><b>Memos:</b></td><td>#memos# memos</td></tr>
+ </tbody>
+ </table>
+ </center>#endifrecords#-->
+
+
+<!--#ifsync#<h2><a name="Sync">Synchronization Information</a></h2>
+ <center>
+ <table border=1>
+ <tbody>
+ <tr><td><b>Last sync attempt:</b></td><td>#lastsync#</td></tr>
+ <tr><td><b>Last successful sync:</b></td><td>#lastsuccsync#</td></tr>
+ <tr><td><b>Last sync with PC (ID):</b></td><td>#lastsyncpc#</td></tr>
+ </tbody>
+ </table>
+ </center>#endifsync#-->
+
+
+<!--#ifpcversion#<h2><a name="Version">Version Information (Desktop)</a></h2>
+ <center>
+ <table border=1>
+ <thead>
+ <tr><th scope=col>Application</th><th scope=col>Version</th></tr>
+ </thead>
+ <tbody>
+ <tr><td><b>Operating System:</b></td><td>#os#</td></tr>
+ <tr><td><b>Hostname:</b></td><td>#hostname#</td></tr>
+ <tr><td><b>Qt Version:</b></td><td>#qt#</td></tr>
+ <tr><td><b>KDE Libraries Version:</b></td><td>#kde#</td></tr>
+ <tr><td><b>KPilot Version:</b></td><td>#kpilot#</td></tr>
+ <tr><td><b>Pilot-Link Version:</b></td><td>#pilotlink#</td></tr>
+ </tbody>
+ </table>
+ </center>#endifpcversion#-->
+
+
+<!--#ifpalmversion#<h2><a name="PalmVersion">Version Information (Handheld)</a></h2>
+ <center>
+ <table border=1>
+ <thead>
+ <tr><th scope=col>Application</th><th scope=col>Version</th></tr>
+ </thead>
+ <tbody>
+ <tr><td><b>PalmOS:</b></td><td>#palmos#</td></tr>
+ </tbody>
+ </table>
+ </center>#endifpalmversion#-->
+
+
+<!--#ifdebug#<h2><a name="Debug">Debug Information</a></h2>
+ <center>
+ <table border=1>
+ <tr><td><pre>#debug#</pre></td></tr>
+ </table>
+ </center>#endifdebug#-->
+
+
+ <p>&nbsp;</p>
+ <hr>
+ <font size="-1">Page created #date# by the SysInfo conduit of <a href="http://www.kpilot.org/">KPilot</a>.</font>
+</body>
+</html>
diff --git a/kpilot/conduits/sysinfoconduit/Template.txt b/kpilot/conduits/sysinfoconduit/Template.txt
new file mode 100644
index 000000000..8796e44a1
--- /dev/null
+++ b/kpilot/conduits/sysinfoconduit/Template.txt
@@ -0,0 +1,76 @@
+KPilot System Information Page
+==============================
+
+<!--#ifhardware#
+-) Hardware Information
+ DeviceID: #deviceid#
+ Device name: #devicename#
+ Device model: #devicemodel#
+ Manufacturer: #manufacturer#
+ Connected via: #devicetype#
+#endifhardware#-->
+
+<!--#ifuser#
+-) User Information
+ Handheld User Name: #username#
+ Handheld Password: #pw#
+ Handheld User ID: #uid#
+ Viewer ID: #viewerid#
+#endifuser#-->
+
+<!--#ifmemory#
+-) Memory Information
+ ROM: #rom# kB total
+ Total RAM: #totalmem# kB total
+ Free RAM: #freemem# kB fre
+#endifmemory#-->
+
+<!--#ifstorage#
+-) Storage Information
+ Cards: #cards#
+#endifstorage#-->
+
+<!--#ifdblist#
+-) List of Databases on Handheld
+ Available Databases: #dblist[
+ %0 (%1, %2)]#
+#endifdblist#-->
+
+<!--#ifrecords#
+-) Number of addresses, todos, events, and memos
+ Addresses: #addresses# entries in Addressbook
+ Events: #events# entries in Calendar
+ Todos: #todos# entries in ToDo list
+ Memos: #memos# memos
+#endifrecords#-->
+
+<!--#ifsync#
+-) Synchronization Information
+ Last sync attempt: #lastsync#
+ Last successful sync: #lastsuccsync#
+ Last sync with PC (ID): #lastsyncpc#
+#endifsync#-->
+
+<!--#ifpcversion#
+-) Version Information (Desktop)
+ Operating System: #os#
+ Hostname: #hostname#
+ Qt Version: #qt#
+ KDE Version: #kde#
+ KPilot Version: #kpilot#
+ Pilot-Link Version: #pilotlink#
+#endifpcversion#-->
+
+<!--#ifpalmversion#
+-) Version Information (Handheld)
+ PalmOS: #palmos#
+#endifpalmversion#-->
+
+<!--#ifdebug#
+-) Debug Information
+ #debug#
+#endifdebug#-->
+
+
+------------------------------------------------------------
+Page created #date# by the SysInfo conduit of KPilot.
diff --git a/kpilot/conduits/sysinfoconduit/sysinfo-conduit.cc b/kpilot/conduits/sysinfoconduit/sysinfo-conduit.cc
new file mode 100644
index 000000000..b3e69b65c
--- /dev/null
+++ b/kpilot/conduits/sysinfoconduit/sysinfo-conduit.cc
@@ -0,0 +1,611 @@
+/* KPilot
+**
+** Copyright (C) 2003 by Reinhold Kainhofer
+**
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org.
+*/
+
+#include "options.h"
+
+#include <pi-version.h>
+
+#include <qtimer.h>
+#include <qdir.h>
+#include <qfileinfo.h>
+#include <qregexp.h>
+#include <kconfig.h>
+#include <kdebug.h>
+
+#include <pilotSysInfo.h>
+#include <pilotUser.h>
+#include <pilotCard.h>
+#include <kpilotlink.h>
+#include <kstandarddirs.h>
+#include <pilotSerialDatabase.h>
+
+#include <sys/utsname.h>
+
+#include "sysinfo-factory.h"
+#include "sysinfo-conduit.moc"
+#include "sysinfoSettings.h"
+
+const QString SysInfoConduit::defaultpage = CSL1("KPilot System Information Page\n"
+"==============================\n"
+"(Kpilot was unable to find the correct template file, \n"
+"so this simple template was used.)\n\n"
+"<!--#ifhardware#\n"
+"-) Hardware Information\n"
+" DeviceID: #deviceid#\n"
+" Device name: #devicename#\n"
+" Device model: #devicemodel#\n"
+" Manufacturer: #manufacturer#\n"
+" Connected via: #devicetype#\n"
+"#endifhardware#-->\n"
+"\n"
+"<!--#ifuser#\n"
+"-) User Information\n"
+" Handheld User Name: #username#\n"
+" Handheld Password: #pw#\n"
+" Handheld User ID: #uid#\n"
+" Viewer ID: #viewerid#\n"
+"#endifuser#-->\n"
+"\n"
+"<!--#ifmemory#\n"
+"-) Memory Information\n"
+" ROM: #rom# kB total\n"
+" Total RAM: #totalmem# kB total\n"
+" Free RAM: #freemem# kB free\n"
+"#endifmemory#-->\n"
+"\n"
+"<!--#ifstorage#\n"
+"-) Storage Information\n"
+" Number of cards: #cards#\n"
+" Memory on cards: #storagemem#\n"
+"#endifstorage#-->\n"
+"\n"
+"<!--#ifdblist#\n"
+"-) List of Databases on Handheld\n"
+" Available Databases: #dblist(%1,)#\n"
+"#endifdblist#-->\n"
+"\n"
+"<!--#ifrecords#\n"
+"-) Number of addresses, to-dos, events, and memos\n"
+" Addresses: #addresses# entries in Addressbook\n"
+" Events: #events# entries in Calendar\n"
+" To-dos: #todos# entries in To-do list\n"
+" Memos: #memos# memos\n"
+"#endifrecords#-->\n"
+"\n"
+"<!--#ifsync#\n"
+"-) Synchronization Information\n"
+" Last sync attempt: #lastsync#\n"
+" Last successful sync: #lastsuccsync#\n"
+" Last sync with PC (ID): #lastsyncpc#\n"
+"#endifsync#-->\n"
+"\n"
+"<!--#ifpcversion#\n"
+"-) Version Information (Desktop)\n"
+" Operating System: #os#\n"
+" Hostname: #hostname#\n"
+" Qt Version: #qt#\n"
+" KDE Version: #kde#\n"
+" KPilot Version: #kpilot#\n"
+" Pilot-Link Version: #pilotlink#\n"
+"#endifpcversion#-->\n"
+"\n"
+"<!--#ifpalmversion#\n"
+"-) Version Information (Handheld)\n"
+" PalmOS: #palmos#\n"
+"#endifpalmversion#-->\n"
+"\n"
+"<!--#ifdebug#\n"
+"-) Debug Information\n"
+" #debug#\n"
+"#endifdebug#-->\n"
+"\n"
+"------------------------------------------------------------\n"
+"Page created <!--#date#--> by the KPilot System Information conduit.\n"
+"");
+
+
+ /** possible fields in the templates are:
+ * - hardware
+ * - user
+ * - memory
+ * - storage
+ * - dblist
+ * - recnumber
+ * - syncinfo
+ * - pcversion
+ * - palmversion
+ * - debug
+ */
+
+
+// Something to allow us to check what revision
+// the modules are that make up a binary distribution.
+
+extern "C"
+{
+
+unsigned long version_conduit_sysinfo = Pilot::PLUGIN_API;
+
+}
+
+
+
+SysInfoConduit::SysInfoConduit(KPilotLink * o,
+ const char *n,
+ const QStringList & a) :
+ ConduitAction(o, n, a)
+{
+ FUNCTIONSETUP;
+ fConduitName=i18n("System Information");
+}
+
+
+
+SysInfoConduit::~SysInfoConduit()
+{
+ FUNCTIONSETUP;
+}
+
+
+
+void SysInfoConduit::readConfig()
+{
+ fOutputFile = SysinfoSettings::outputFile();
+ fOutputType = (eOutputTypeEnum) SysinfoSettings::outputFormat();
+ fTemplateFile = SysinfoSettings::templateFile();
+ fHardwareInfo = SysinfoSettings::hardwareInfo();
+ fUserInfo = SysinfoSettings::userInfo();
+ fMemoryInfo = SysinfoSettings::memoryInfo();
+ fStorageInfo = SysinfoSettings::storageInfo();
+ fDBList = SysinfoSettings::databaseList();
+ fRecordNumber = SysinfoSettings::recordNumbers();
+ fSyncInfo = SysinfoSettings::syncInfo();
+ fKDEVersion = SysinfoSettings::kDEVersion();
+ fPalmOSVersion = SysinfoSettings::palmOSVersion();
+ fDebugInfo = SysinfoSettings::debugInformation();
+}
+
+
+/* virtual */ bool SysInfoConduit::exec()
+{
+ FUNCTIONSETUP;
+
+ readConfig();
+
+ QTimer::singleShot(0, this, SLOT(hardwareInfo()));
+ return true;
+}
+
+void SysInfoConduit::hardwareInfo()
+{
+ FUNCTIONSETUP;
+ if (fHardwareInfo) {
+ QString unknown = i18n("unknown");
+
+ /* Retrieve values for
+ * - #deviceid#
+ * - #devicename#
+ * - #devicemodel#
+ * - #manufactorer#
+ * - #devicetype#
+ */
+ KPilotSysInfo sysinfo = fHandle->getSysInfo();
+ fValues[CSL1("deviceid")] = QString::fromLatin1(sysinfo.getProductID());
+
+ const KPilotCard *device = fHandle->getCardInfo();
+ if (device)
+ {
+ fValues[CSL1("devicename")] = QString::fromLatin1(device->getCardName());
+ fValues[CSL1("devicemodel")] = unknown; // TODO
+ fValues[CSL1("manufacturer")] = QString::fromLatin1(device->getCardManufacturer());
+ }
+ else
+ {
+ fValues[CSL1("devicename")] = unknown;
+ fValues[CSL1("devicemodel")] = unknown;
+ fValues[CSL1("manufacturer")] = unknown;
+ }
+
+ fValues[CSL1("devicetype")] = unknown;
+
+ KPILOT_DELETE(device);
+ keepParts.append(CSL1("hardware"));
+ } else removeParts.append(CSL1("hardware"));
+ QTimer::singleShot(0, this, SLOT(userInfo()));
+}
+
+void SysInfoConduit::userInfo()
+{
+ FUNCTIONSETUP;
+ if (fUserInfo)
+ {
+ /* Retrieve values for
+ * - #username#
+ * - #uid#
+ */
+ KPilotUser user=fHandle->getPilotUser();
+ fValues[CSL1("username")] = user.name();
+ if (user.passwordLength()>0)
+ {
+ fValues[CSL1("pw")] = i18n("Password set");
+ }
+ else
+ {
+ fValues[CSL1("pw")] = i18n("No password set");
+ }
+ fValues[CSL1("uid")] = QString::number(user.data()->userID);
+ fValues[CSL1("viewerid")] = QString::number(user.data()->viewerID);
+ keepParts.append(CSL1("user"));
+ }
+ else
+ {
+ removeParts.append(CSL1("user"));
+ }
+ QTimer::singleShot(0, this, SLOT(memoryInfo()));
+}
+
+void SysInfoConduit::memoryInfo()
+{
+ FUNCTIONSETUP;
+ if (fMemoryInfo) {
+ /* Retrieve values for
+ * - #rom#
+ * - #totalmem#
+ * - #freemem#
+ */
+ const KPilotCard *device = fHandle->getCardInfo();
+ if (device)
+ {
+ fValues[CSL1("rom")] = QString::number(device->getRomSize()/1024);
+ fValues[CSL1("totalmem")] = QString::number(device->getRamSize()/1024);
+ fValues[CSL1("freemem")] = QString::number(device->getRamFree()/1024);
+ }
+ keepParts.append(CSL1("memory"));
+ } else removeParts.append(CSL1("memory"));
+ QTimer::singleShot(0, this, SLOT(storageInfo()));
+}
+
+void SysInfoConduit::storageInfo()
+{
+ FUNCTIONSETUP;
+ if (fStorageInfo) {
+ /* Retrieve values for
+ * - $cards$
+ */
+ const KPilotCard *device = fHandle->getCardInfo(1);
+ if (device) {
+ fValues[CSL1("cards")] = CSL1("%1 (%2, %3 kB of %3 kB free)")
+ .arg(QString::fromLatin1(device->getCardName()))
+ .arg(QString::fromLatin1(device->getCardManufacturer()))
+ .arg(device->getRamFree()/1024)
+ .arg(device->getRamSize()/1024);
+ KPILOT_DELETE(device);
+ } else {
+ fValues[CSL1("cards")] = i18n("No Cards available via pilot-link");
+ }
+ keepParts.append(CSL1("storage"));
+ } else removeParts.append(CSL1("storage"));
+ QTimer::singleShot(0, this, SLOT(dbListInfo()));
+}
+
+void SysInfoConduit::dbListInfo()
+{
+ FUNCTIONSETUP;
+ if (fDBList) {
+ /* Retrieve values for
+ * - #dblist(structure)#
+ */
+ dblist=deviceLink()->getDBList();
+ keepParts.append(CSL1("dblist"));
+ } else removeParts.append(CSL1("dblist"));
+ QTimer::singleShot(0, this, SLOT(recNumberInfo()));
+}
+
+void SysInfoConduit::recNumberInfo()
+{
+ FUNCTIONSETUP;
+ if (fRecordNumber) {
+ /* Retrieve values for
+ * - #addresses#
+ * - #events#
+ * - #todos#
+ * - #memos#
+ */
+ PilotDatabase *fDatabase = 0L;
+ QString ERROR = CSL1("ERROR");
+ fValues[CSL1("addresses")] = ERROR;
+ fValues[CSL1("events")] = ERROR;
+ fValues[CSL1("todos")] = ERROR;
+ fValues[CSL1("memos")] = ERROR;
+ fDatabase = deviceLink()->database(CSL1("AddressDB"));
+ if (fDatabase) {
+ fValues[CSL1("addresses")] = QString::number(fDatabase->recordCount());
+ KPILOT_DELETE(fDatabase);
+ }
+ fDatabase = deviceLink()->database(CSL1("DatebookDB"));
+ if (fDatabase) {
+ fValues[CSL1("events")] = QString::number(fDatabase->recordCount());
+ KPILOT_DELETE(fDatabase);
+ }
+ fDatabase = deviceLink()->database(CSL1("ToDoDB"));
+ if (fDatabase) {
+ fValues[CSL1("todos")] = QString::number(fDatabase->recordCount());
+ KPILOT_DELETE(fDatabase);
+ }
+ fDatabase = deviceLink()->database(CSL1("MemoDB"));
+ if (fDatabase) {
+ fValues[CSL1("memos")] = QString::number(fDatabase->recordCount());
+ KPILOT_DELETE(fDatabase);
+ }
+ keepParts.append(CSL1("records"));
+ } else removeParts.append(CSL1("records"));
+ QTimer::singleShot(0, this, SLOT(syncInfo()));
+}
+
+void SysInfoConduit::syncInfo()
+{
+ FUNCTIONSETUP;
+ if (fSyncInfo) {
+ /* Retrieve values for
+ * - #lastsync#
+ * - #lastsuccsync#
+ * - #lastsyncpc#
+ */
+ KPilotUser user = deviceLink()->getPilotUser();
+ time_t lastsync = user.getLastSyncDate();
+ QDateTime qlastsync;
+ qlastsync.setTime_t(lastsync);
+ fValues[CSL1("lastsync")] = qlastsync.toString(Qt::LocalDate);
+ lastsync = user.getLastSuccessfulSyncDate();
+ qlastsync.setTime_t(lastsync);
+ fValues[CSL1("lastsuccsync")] = qlastsync.toString(Qt::LocalDate);
+ fValues[CSL1("lastsyncpc")] = QString::number(user.getLastSyncPC());
+ keepParts.append(CSL1("sync"));
+ } else removeParts.append(CSL1("sync"));
+ QTimer::singleShot(0, this, SLOT(pcVersionInfo()));
+}
+
+void SysInfoConduit::pcVersionInfo()
+{
+ FUNCTIONSETUP;
+ if (fKDEVersion) {
+ /* Retrieve values for
+ * - #os#
+ * - #qt#
+ * - #kde#
+ * - #kpilot#
+ * - #pilotlink#
+ */
+ fValues[CSL1("kpilot")] = QString::fromLatin1(KPILOT_VERSION);
+ fValues[CSL1("kde")] = i18n("unknown");
+ fValues[CSL1("qt")] = i18n("unknown");
+ fValues[CSL1("os")] = i18n("unknown");
+ fValues[CSL1("hostname")] = i18n("unknown");
+ struct utsname name;
+ if (uname (&name) >= 0) {
+ fValues[CSL1("os")] = CSL1("%1 %3, %5")
+ .arg(QString::fromLatin1(name.sysname))
+ .arg(QString::fromLatin1(name.release))
+ .arg(QString::fromLatin1(name.machine));
+ fValues[CSL1("hostname")] = CSL1("%2").arg(QString::fromLatin1(name.nodename));
+ }
+#ifdef KDE_VERSION_STRING
+ fValues[CSL1("kde")] = QString::fromLatin1(KDE_VERSION_STRING);
+#endif
+#ifdef QT_VERSION_STR
+ fValues[CSL1("qt")] = QString::fromLatin1(QT_VERSION_STR);
+#endif
+ fValues[CSL1("pilotlink")] = CSL1("%1.%2.%3%4")
+ .arg(PILOT_LINK_VERSION)
+ .arg(PILOT_LINK_MAJOR)
+ .arg(PILOT_LINK_MINOR)
+#ifdef PILOT_LINK_PATCH
+ .arg(QString::fromLatin1(PILOT_LINK_PATCH));
+#else
+ .arg(QString());
+#endif
+ keepParts.append(CSL1("pcversion"));
+ } else removeParts.append(CSL1("pcversion"));
+ QTimer::singleShot(0, this, SLOT(palmVersionInfo()));
+}
+
+void SysInfoConduit::palmVersionInfo()
+{
+ FUNCTIONSETUP;
+ if (fPalmOSVersion) {
+ /* Retrieve values for
+ * - #palmos#
+ */
+/* fValues["palmos"] = QString("PalmOS %1.%2 (compat %3.%4)")
+ .arg(fHandle->getSysInfo()->getMajorVersion())
+ .arg(fHandle->getSysInfo()->getMinorVersion())
+ .arg(fHandle->getSysInfo()->getCompatMajorVersion())
+ .arg(fHandle->getSysInfo()->getCompatMinorVersion());*/
+ KPilotSysInfo i = deviceLink()->getSysInfo();
+ fValues[CSL1("palmos")] = CSL1("PalmOS %1.%2").arg(i.getMajorVersion()).arg(i.getMinorVersion());
+
+ keepParts.append(CSL1("palmversion"));
+ } else removeParts.append(CSL1("palmversion"));
+ QTimer::singleShot(0, this, SLOT(debugInfo()));
+}
+
+void SysInfoConduit::debugInfo()
+{
+ FUNCTIONSETUP;
+ if (fDebugInfo) {
+ /* Retrieve values for
+ * - #debug#
+ */
+ fValues[CSL1("debug")] = i18n("No debug data");
+ keepParts.append(CSL1("debug"));
+ } else removeParts.append(CSL1("debug"));
+ QTimer::singleShot(0, this, SLOT(writeFile()));
+}
+
+void SysInfoConduit::writeFile()
+{
+ FUNCTIONSETUP;
+
+ fValues[CSL1("date")] = QDateTime::currentDateTime().toString(Qt::LocalDate);
+
+ QString output;
+ // Open the template file
+ QString templatefile;
+ switch(fOutputType)
+ {
+ case eOutputText:
+ templatefile=locate("data", CSL1("kpilot/sysinfoconduit/Template.txt"));
+ break;
+ case eOutputTemplate:
+ templatefile=fTemplateFile;
+ break;
+ case eOutputHTML:
+ default:
+ templatefile=locate("data", CSL1("kpilot/sysinfoconduit/Template.html"));
+ break;
+ }
+
+ // Read in the template, close the file
+ bool loaded=false;
+ if (!templatefile.isEmpty()){
+#ifdef DEBUG
+ DEBUGKPILOT<<"Loading template file "<<templatefile<<endl;
+#endif
+ QFile infile(templatefile);
+ if (infile.open(IO_ReadOnly)) {
+ QTextStream instream(&infile);
+ output = instream.read();
+ infile.close();
+ loaded=true;
+ }
+ }
+
+ if (!loaded)
+ {
+ WARNINGKPILOT << "Loading template file " << templatefile
+ <<" failed. Using default template instead." << endl;
+ output=defaultpage;
+ }
+
+ // Remove all parts not extracted
+ for ( QStringList::Iterator it = removeParts.begin(); it != removeParts.end(); ++it ) {
+ QRegExp re(CSL1("<!--#if%1#.*#endif%1#-->").arg(*it).arg(*it));
+ re.setMinimal(true);
+ output.remove(re);
+ }
+ for ( QStringList::Iterator it = keepParts.begin(); it != keepParts.end(); ++it ) {
+ QRegExp re(CSL1("<!--#if%1#(.*)#endif%1#-->").arg(*it).arg(*it));
+ re.setMinimal(true);
+ output.replace(re, CSL1("\\1"));
+ }
+
+ // Do a loop through all keys in fValues
+ QMap<QString,QString>::Iterator it;
+ for ( it = fValues.begin(); it != fValues.end(); ++it ) {
+ output.replace(CSL1("#%1#").arg(it.key()), it.data());
+ }
+
+ // Insert the list of databases
+ QRegExp re(CSL1("#dblist\\[(.*)\\]#"));
+ re.setMinimal(true);
+ while (re.search(output)>=0){
+ QString dbstring;
+ QString subpatt=re.cap(1);
+ for (KPilotLink::DBInfoList::ConstIterator i = dblist.begin(); i != dblist.end(); ++i ) {
+ DBInfo dbi = *i;
+ QString newpatt(subpatt);
+ char tmpchr[5];
+ ::memset(&tmpchr[0], 0, 5);
+ /* Patterns for the dblist argument:
+ * %0 .. Database name
+ * %1 .. type
+ * %2 .. creator
+ * %3 .. index
+ * %4 .. flags
+ * %5 .. miscFlags
+ * %6 .. version
+ * %7 .. createDate
+ * %8 .. modifyDate
+ * %9 .. backupDate
+ */
+ newpatt.replace(CSL1("%0"), QString::fromLatin1(dbi.name));
+ set_long(&tmpchr[0],dbi.type);
+ newpatt.replace(CSL1("%1"), QString::fromLatin1(tmpchr));
+ set_long(&tmpchr[0],dbi.creator);
+ newpatt.replace(CSL1("%2"), QString::fromLatin1(tmpchr));
+ newpatt.replace(CSL1("%3"), QString::number(dbi.index));
+ newpatt.replace(CSL1("%4"), QString::number(dbi.flags));
+ newpatt.replace(CSL1("%5"), QString::number(dbi.miscFlags));
+ newpatt.replace(CSL1("%6"), QString::number(dbi.version));
+ QDateTime tm;
+ tm.setTime_t(dbi.createDate);
+ newpatt.replace(CSL1("%7"), tm.toString(Qt::LocalDate));
+ tm.setTime_t(dbi.modifyDate);
+ newpatt.replace(CSL1("%8"), tm.toString(Qt::LocalDate));
+ tm.setTime_t(dbi.backupDate);
+ newpatt.replace(CSL1("%9"), tm.toString(Qt::LocalDate));
+
+ dbstring.append(newpatt);
+ }
+ // Now, just replace the whole found pattern by the string we just constructed.
+ output.replace(re.cap(0), dbstring);
+ }
+
+ // Write out the result
+ QFile outfile(fOutputFile);
+#ifdef DEBUG
+ DEBUGKPILOT << fname << ": Writing file <" << fOutputFile << ">" << endl;
+#endif
+ if (fOutputFile.isEmpty() || (!outfile.open(IO_WriteOnly)) ) {
+ QFileInfo fi(QDir::home(), CSL1("KPilotSysInfo.")+QFileInfo(templatefile).extension() );
+ fOutputFile=fi.absFilePath();
+ WARNINGKPILOT << "Unable to open output file, using " << fOutputFile << " instead." << endl;
+ emit logMessage(i18n("Unable to open output file, using %1 instead.").arg(fOutputFile));
+ outfile.setName(fOutputFile);
+ if (!outfile.open(IO_WriteOnly)) {
+ WARNINGKPILOT<< "Unable to open " << fOutputFile << endl;
+ emit logError(i18n("Unable to open %1").arg(fOutputFile));
+ QTimer::singleShot(0, this, SLOT(cleanup()));
+ return;
+ }
+ }
+
+ // Finally, write the actual text out to the file.
+ QTextStream outstream(&outfile);
+ outstream<<output;
+ outfile.close();
+
+ emit logMessage(i18n("Handheld system information written to the file %1").arg(fOutputFile));
+ QTimer::singleShot(0, this, SLOT(cleanup()));
+}
+
+void SysInfoConduit::cleanup()
+{
+ FUNCTIONSETUP;
+ // Nothing to clean up so far (Do I have memory leaks somewhere?)
+ emit syncDone(this);
+}
diff --git a/kpilot/conduits/sysinfoconduit/sysinfo-conduit.h b/kpilot/conduits/sysinfoconduit/sysinfo-conduit.h
new file mode 100644
index 000000000..05bc395d3
--- /dev/null
+++ b/kpilot/conduits/sysinfoconduit/sysinfo-conduit.h
@@ -0,0 +1,79 @@
+#ifndef _SysInfo_CONDUIT_H
+#define _SysInfo_CONDUIT_H
+/* sysinfo-conduit.h KPilot
+**
+** Copyright (C) 2003 by Reinhold Kainhofer
+**
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+
+#include <plugin.h>
+
+class SysInfoConduit : public ConduitAction
+{
+ Q_OBJECT
+public:
+ SysInfoConduit(
+ KPilotLink *o,
+ const char *n = 0L,
+ const QStringList &a = QStringList() );
+ virtual ~SysInfoConduit();
+ virtual bool exec();
+
+public slots:
+ void hardwareInfo();
+ void userInfo();
+ void memoryInfo();
+ void storageInfo();
+ void dbListInfo();
+ void recNumberInfo();
+ void syncInfo();
+ void pcVersionInfo();
+ void palmVersionInfo();
+ void debugInfo();
+ void writeFile();
+ void cleanup();
+
+protected:
+ void readConfig();
+private:
+ QMap<QString,QString> fValues;
+
+ bool fHardwareInfo, fUserInfo, fMemoryInfo, fStorageInfo,
+ fDBList, fRecordNumber, fSyncInfo,
+ fKDEVersion, fPalmOSVersion, fDebugInfo;
+ QString fOutputFile, fTemplateFile;
+ enum eOutputTypeEnum {
+ eOutputHTML=0,
+ eOutputText,
+ eOutputTemplate
+ } fOutputType;
+
+ KPilotLink::DBInfoList dblist;
+ QStringList removeParts;
+ QStringList keepParts;
+ static const QString defaultpage;
+} ;
+
+#endif
diff --git a/kpilot/conduits/sysinfoconduit/sysinfo-factory.cc b/kpilot/conduits/sysinfoconduit/sysinfo-factory.cc
new file mode 100644
index 000000000..d03dc0b04
--- /dev/null
+++ b/kpilot/conduits/sysinfoconduit/sysinfo-factory.cc
@@ -0,0 +1,43 @@
+/* SysInfo-factory.cc KPilot
+**
+** Copyright (C) 2003 by Reinhold Kainhofer
+**
+** This file defines the factory for the SysInfo-conduit plugin.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include "options.h"
+#include "pluginfactory.h"
+
+#include "sysinfo-conduit.h"
+#include "sysinfo-setup.h"
+
+extern "C"
+{
+
+void *init_conduit_sysinfo()
+{
+ return new ConduitFactory<SysInfoWidgetConfig,SysInfoConduit>;
+}
+
+}
diff --git a/kpilot/conduits/sysinfoconduit/sysinfo-factory.h b/kpilot/conduits/sysinfoconduit/sysinfo-factory.h
new file mode 100644
index 000000000..66ae5ae38
--- /dev/null
+++ b/kpilot/conduits/sysinfoconduit/sysinfo-factory.h
@@ -0,0 +1,36 @@
+#ifndef _SYSINFO_FACTORY_H
+#define _SYSINFO_FACTORY_H
+/* SysInfo-factory.h KPilot
+**
+** Copyright (C) 2003 by Reinhold Kainhofer
+**
+** This file defines the factory for the SysInfo-conduit plugin.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+extern "C"
+{
+ void *init_libsysinfoconduit();
+}
+
+#endif
diff --git a/kpilot/conduits/sysinfoconduit/sysinfo-setup.cc b/kpilot/conduits/sysinfoconduit/sysinfo-setup.cc
new file mode 100644
index 000000000..ed7419ab3
--- /dev/null
+++ b/kpilot/conduits/sysinfoconduit/sysinfo-setup.cc
@@ -0,0 +1,198 @@
+/* SysInfo-setup.cc KPilot
+**
+** Copyright (C) 2003 by Reinhold Kainhofer
+**
+** This file defines the setup dialog for the SysInfo-conduit plugin.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include "options.h"
+
+#include <qtabwidget.h>
+#include <qradiobutton.h>
+#include <qcheckbox.h>
+#include <qbuttongroup.h>
+#include <qlistview.h>
+
+#include <kaboutdata.h>
+#include <kapplication.h>
+#include <kurlrequester.h>
+
+#include "sysinfo-setup_dialog.h"
+
+#include "sysinfo-factory.h"
+#include "sysinfo-setup.h"
+#include "sysinfoSettings.h"
+
+
+typedef struct { const char *name; bool (*accessor)(); void (*mutator)(bool); } sysinfoEntry_t;
+
+const sysinfoEntry_t sysinfoEntries[] =
+{
+ { I18N_NOOP("HardwareInfo"), SysinfoSettings::hardwareInfo, SysinfoSettings::setHardwareInfo },
+ { I18N_NOOP("UserInfo"), SysinfoSettings::userInfo, SysinfoSettings::setUserInfo },
+ { I18N_NOOP("MemoryInfo"), SysinfoSettings::memoryInfo, SysinfoSettings::setMemoryInfo },
+ { I18N_NOOP("StorageInfo"), SysinfoSettings::storageInfo, SysinfoSettings::setStorageInfo },
+ { I18N_NOOP("DatabaseList"), SysinfoSettings::databaseList, SysinfoSettings::setDatabaseList },
+ { I18N_NOOP("RecordNumbers"), SysinfoSettings::recordNumbers, SysinfoSettings::setRecordNumbers},
+ { I18N_NOOP("SyncInfo"), SysinfoSettings::syncInfo, SysinfoSettings::setSyncInfo },
+ { I18N_NOOP("KDEVersion"), SysinfoSettings::kDEVersion, SysinfoSettings::setKDEVersion },
+ { I18N_NOOP("PalmOSVersion"), SysinfoSettings::palmOSVersion, SysinfoSettings::setPalmOSVersion },
+ { I18N_NOOP("DebugInformation"), SysinfoSettings::debugInformation, SysinfoSettings::setDebugInformation },
+ { 0L, 0L, 0L }
+} ;
+
+
+/*
+** The QCheckListItems used in the list of parts to print have
+** several text fields with special meanings.
+** 0: The text displayed in the list.
+** 1: The index of the item in the sysinfoEntries array.
+** 2: This string is empty if the part was originally not checked,
+** and non-empty (probably "1") if the part was originally checked.
+** This is used to detect changes in the configuration.
+** We introduce some defines for these numbers.
+*/
+
+#define PART_NAME (0)
+#define PART_KEY (1)
+#define PART_SETTING (2)
+
+/*
+** This is a convenience define to update an item's "original setting".
+*/
+#define updateSetting(i) { QCheckListItem *ubbu=(i); \
+ ubbu->setText(PART_SETTING,(ubbu->isOn() ? CSL1("1") : QString::null)); }
+
+
+SysInfoWidgetConfig::SysInfoWidgetConfig(QWidget *w, const char *n) :
+ ConduitConfigBase(w,n),
+ fConfigWidget(new SysInfoWidget(w))
+{
+ FUNCTIONSETUP;
+
+ KAboutData *fAbout = new KAboutData("SysInfoConduit",
+ I18N_NOOP("KPilot System Information conduit"),
+ KPILOT_VERSION,
+ I18N_NOOP("Retrieves System, Hardware, and User Info from the Handheld and stores them to a file."),
+ KAboutData::License_GPL,
+ "(C) 2003, Reinhold Kainhofer");
+ fAbout->addAuthor("Reinhold Kainhofer",
+ I18N_NOOP("Primary Author"), "reinhold@kainhofer.com", "http://reinhold.kainhofer.com/");
+
+ ConduitConfigBase::addAboutPage(fConfigWidget->tabWidget,fAbout);
+ fWidget=fConfigWidget;
+
+ QObject::connect(fConfigWidget->fOutputFile,SIGNAL(textChanged(const QString&)),
+ this,SLOT(modified()));
+ QObject::connect(fConfigWidget->fTemplateFile,SIGNAL(textChanged(const QString&)),
+ this,SLOT(modified()));
+ QObject::connect(fConfigWidget->fOutputType,SIGNAL(clicked(int)),
+ this,SLOT(modified()));
+ fConduitName=i18n("System Information");
+}
+
+void SysInfoWidgetConfig::commit()
+{
+ FUNCTIONSETUP;
+
+ SysinfoSettings::setOutputFile(
+ fConfigWidget->fOutputFile->url() );
+ SysinfoSettings::setTemplateFile(
+ fConfigWidget->fTemplateFile->url() );
+ SysinfoSettings::setOutputFormat(
+ fConfigWidget->fOutputType->id(fConfigWidget->fOutputType->selected()));
+
+ QListViewItem *i = fConfigWidget->fPartsList->firstChild();
+ QCheckListItem *ci = dynamic_cast<QCheckListItem *>(i);
+ while(ci)
+ {
+#ifdef DEBUG
+ DEBUGKPILOT << fname << ": Saving " << ci->text(PART_NAME)
+ << (ci->isOn() ? " on" : " off") << endl;
+#endif
+ int index=ci->text(PART_KEY).toInt();
+ if (0<=index && index<=10)
+ {
+ const sysinfoEntry_t *p = sysinfoEntries+index;
+ p->mutator(ci->isOn());
+ }
+ updateSetting(ci);
+ i=i->nextSibling();
+ ci = dynamic_cast<QCheckListItem *>(i);
+ }
+ SysinfoSettings::self()->writeConfig();
+ unmodified();
+}
+
+void SysInfoWidgetConfig::load()
+{
+ FUNCTIONSETUP;
+ SysinfoSettings::self()->readConfig();
+
+ const sysinfoEntry_t *p = sysinfoEntries;
+ QCheckListItem *i = 0L;
+ while (p && p->name)
+ {
+ i = new QCheckListItem(fConfigWidget->fPartsList,i18n(p->name),QCheckListItem::CheckBox);
+ // by default let the sysinfo conduit write out all available information
+ i->setOn( p->accessor() );
+ i->setText(PART_KEY, QString::number(p-sysinfoEntries)); // store index there
+ updateSetting(i);
+#ifdef DEBUG
+ DEBUGKPILOT << fname << ": Loaded " << p->name
+ << (i->isOn() ? " on" : " off") << endl;
+#endif
+
+ p++;
+ }
+ fConfigWidget->fOutputFile->setURL( SysinfoSettings::outputFile() );
+ fConfigWidget->fTemplateFile->setURL( SysinfoSettings::templateFile() );
+ fConfigWidget->fOutputType->setButton( SysinfoSettings::outputFormat() );
+ unmodified();
+}
+
+/* virtual */ bool SysInfoWidgetConfig::isModified() const
+{
+ FUNCTIONSETUP;
+ if (fModified) return true;
+
+ QListViewItem *i = fConfigWidget->fPartsList->firstChild();
+ QCheckListItem *ci = dynamic_cast<QCheckListItem *>(i);
+
+ while(ci)
+ {
+ bool current = ci->isOn();
+ bool original = !ci->text(PART_SETTING).isEmpty();
+#ifdef DEBUG
+ DEBUGKPILOT << fname << ": Checking " << ci->text(PART_KEY)
+ << " was " << (original ? " on" : " off")
+ << " now " << (current ? " on" : " off") << endl;
+#endif
+
+ if (current!=original) return true;
+ i=i->nextSibling();
+ ci = dynamic_cast<QCheckListItem *>(i);
+ }
+ return false;
+}
diff --git a/kpilot/conduits/sysinfoconduit/sysinfo-setup.h b/kpilot/conduits/sysinfoconduit/sysinfo-setup.h
new file mode 100644
index 000000000..41e55eb86
--- /dev/null
+++ b/kpilot/conduits/sysinfoconduit/sysinfo-setup.h
@@ -0,0 +1,47 @@
+#ifndef _SysInfo_SysInfo_SETUP_H
+#define _SysInfo_SysInfo_SETUP_H
+/* sysinfo-setup.h KPilot
+**
+** Copyright (C) 2003 by Reinhold Kainhofer
+**
+** This file defines the widget and behavior for the config dialog
+** of the KNotes conduit.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include "plugin.h"
+
+class SysInfoWidget;
+
+class SysInfoWidgetConfig : public ConduitConfigBase
+{
+public:
+ SysInfoWidgetConfig(QWidget *parent, const char *);
+ virtual void commit();
+ virtual void load();
+ virtual bool isModified() const;
+protected:
+ SysInfoWidget *fConfigWidget;
+} ;
+
+#endif
diff --git a/kpilot/conduits/sysinfoconduit/sysinfo-setup_dialog.ui b/kpilot/conduits/sysinfoconduit/sysinfo-setup_dialog.ui
new file mode 100644
index 000000000..e4502bb1e
--- /dev/null
+++ b/kpilot/conduits/sysinfoconduit/sysinfo-setup_dialog.ui
@@ -0,0 +1,214 @@
+<!DOCTYPE UI><UI version="3.1" stdsetdef="1">
+<class>SysInfoWidget</class>
+<author>Reinhold Kainhofer</author>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>Form2</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>330</width>
+ <height>232</height>
+ </rect>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QTabWidget" row="0" column="0">
+ <property name="name">
+ <cstring>tabWidget</cstring>
+ </property>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>General</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer row="3" column="1">
+ <property name="name">
+ <cstring>spacer3</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>51</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="KURLRequester" row="0" column="1">
+ <property name="name">
+ <cstring>fOutputFile</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Enter here, or select by clicking the file picker button, the location and file name of the output file used to store the handheld's system information.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel4</cstring>
+ </property>
+ <property name="text">
+ <string>Output &amp;file:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>fOutputFile</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Enter here, or select by clicking the file picker button, the location and file name of the output file used to store the handheld's system information.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QButtonGroup" row="1" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>fOutputType</cstring>
+ </property>
+ <property name="title">
+ <string>Type of Output</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QRadioButton" row="0" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>radioButton3</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;HTML</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Select this option to output the system information data as a HTML document.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="1" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>radioButton4</cstring>
+ </property>
+ <property name="text">
+ <string>Te&amp;xt file</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Select this option to output the system information data as a text document.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="KURLRequester" row="2" column="1">
+ <property name="name">
+ <cstring>fTemplateFile</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Enter here, or select by clicking on the file picker button, the location of the template to be used if you select the Custom template option.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="2" column="0">
+ <property name="name">
+ <cstring>radioButton5</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Custom template:</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Select this option to output the system information data as defined by a custom template. Enter the location of the template in the edit box, or select it clicking on the file picker button.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Parts Included</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer row="1" column="0">
+ <property name="name">
+ <cstring>spacer4</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>21</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QListView" row="0" column="0">
+ <column>
+ <property name="text">
+ <string>Output Type</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <property name="name">
+ <cstring>fPartsList</cstring>
+ </property>
+ <property name="resizeMode">
+ <enum>LastColumn</enum>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Check on this list the types of information about your system and handheld you want to display in the output file.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </widget>
+ </grid>
+</widget>
+<connections>
+ <connection>
+ <sender>radioButton5</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>fTemplateFile</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+</connections>
+<tabstops>
+ <tabstop>tabWidget</tabstop>
+</tabstops>
+<layoutdefaults spacing="6" margin="11"/>
+<includes>
+ <include location="global" impldecl="in implementation">kurlrequester.h</include>
+ <include location="global" impldecl="in implementation">klineedit.h</include>
+ <include location="global" impldecl="in implementation">kpushbutton.h</include>
+</includes>
+</UI>
diff --git a/kpilot/conduits/sysinfoconduit/sysinfoSettings.kcfgc b/kpilot/conduits/sysinfoconduit/sysinfoSettings.kcfgc
new file mode 100644
index 000000000..09337f301
--- /dev/null
+++ b/kpilot/conduits/sysinfoconduit/sysinfoSettings.kcfgc
@@ -0,0 +1,7 @@
+File=sysinfoconduit.kcfg
+ClassName=SysinfoSettings
+Singleton=true
+ItemAccessors=true
+Mutators=true
+GlobalEnums=true
+SetUserTexts=true
diff --git a/kpilot/conduits/sysinfoconduit/sysinfo_conduit.desktop b/kpilot/conduits/sysinfoconduit/sysinfo_conduit.desktop
new file mode 100644
index 000000000..7e7b04380
--- /dev/null
+++ b/kpilot/conduits/sysinfoconduit/sysinfo_conduit.desktop
@@ -0,0 +1,111 @@
+[Desktop Entry]
+Type=Service
+Comment=This conduit writes information about your handheld and the sync to a file.
+Comment[af]=Hierdie pad skryf informasie aangaande die draagbare toestel en sinkronisasie na 'n lêer.
+Comment[bg]=Ð—Ð°Ð¿Ð¸Ñ Ð½Ð° информациÑта отноÑно мобилното уÑтройÑтво във файл
+Comment[bs]=Ovaj conduit ispisuje informacije o ruÄnom raÄunaru i sinhronizuje ih sa datotekom.
+Comment[ca]=Aquest conducte escriu informació a un fitxer a sobre de la vostra agenda electrònica i la sincronització.
+Comment[cs]=Toto propojení zapisuje informace o vašem handheldu a synchronizaci do souboru.
+Comment[cy]=Mae'r cwndid yma yn ysgrifennu gwybodaeth ynglyn â'ch llawiadur a'r cydamseriad i ffeil.
+Comment[da]=Denne kanal skriver information om din håndholdte og synkroniseringen til en fil.
+Comment[de]=Schreibt Daten zum Taschencomputer und den Abgleich in eine Datei
+Comment[el]=Αυτός ο σÏνδεσμος γÏάφει πληÏοφοÏίες σχετικά με τον υπολογιστή παλάμης σας και το συγχÏονισμό Ï€Ïος ένα αÏχείο.
+Comment[es]=Este conducto escribe la información subre su agenda electrónica y la sincronización a un archivo.
+Comment[et]=See kanal salvestab info pihuarvuti kohta failina.
+Comment[eu]=Kanal honek zure agenda elektronikoari buruzko informazioa eta sinkronizazio fitxategi batean gordetzen ditu.
+Comment[fa]=این لوله، اطلاعات دربارۀ دستی شما و ترکیب‌دهی به پرونده را می‌نویسد.
+Comment[fi]=Tämä yhdyskäytävä kirjoittaa tietoja taskutietokoneelta ja synkronoi ne tiedostoon.
+Comment[fr]=Ce canal écrit des informations sur votre périphérique et la synchronisation dans un fichier.
+Comment[fy]=Dit conduit bewarret ynformaasje oer jo handheld en syngronosaasje yn in triem.
+Comment[gl]=Este conducto escribe a información sobre o seu aparello portátil e a sincronización a un ficheiro.
+Comment[hi]=यह कनà¥à¤¡à¥à¤¯à¥‚इट आपके हैंणà¥à¤¡à¤¹à¥‡à¤²à¥à¤¡ के बारे में जानकारी लिखता है तथा à¤à¤• फ़ाइल में सिंक करता है.
+Comment[hu]=Ezzel a csatolóval fájlba lehet kiíratni a kéziszámítógép és a szinkronizálás jellemzőit
+Comment[is]=Þessi rás skrifar upplýsingar um lófatölvuna þína og samstillinguna í skrá.
+Comment[it]=Questo conduit scrive in un file informazioni sul tuo palmare.
+Comment[ja]=ã“ã®ã‚³ãƒ³ã‚¸ãƒƒãƒˆã¯ã‚ãªãŸã®ãƒãƒ³ãƒ‰ãƒ˜ãƒ«ãƒ‰ã®æƒ…報を書ã出ã—ã€ãƒ•ã‚¡ã‚¤ãƒ«ã«åŒæœŸã—ã¾ã™ã€‚
+Comment[ka]=ეს áƒáƒ áƒ®áƒ˜ ინფáƒáƒ áƒ›áƒáƒªáƒ˜áƒáƒ¡ წერს თქვენი პáƒáƒ áƒ¢áƒáƒ¢áƒ˜áƒ£áƒšáƒ˜ მáƒáƒ¬áƒ§áƒáƒ‘ილáƒáƒ‘ის შესáƒáƒ®áƒ”ბ დრáƒáƒ®áƒ“ენს მის სინქრáƒáƒœáƒ˜áƒ–áƒáƒªáƒ˜áƒáƒ¡ ფáƒáƒ˜áƒšáƒ—áƒáƒœ.
+Comment[kk]=Қалта құрылғыңыз туралы мәліметті файла жазу арнаÑÑ‹.
+Comment[km]=បំពង់​នáŸáŸ‡â€‹ážŸážšážŸáŸážšâ€‹áž–áŸážáŸŒáž˜áž¶áž“​អំពី​ឧបករណáŸâ€‹áž™áž½ážšážŠáŸƒâ€‹ážšáž”ស់​អ្នក និង​ការ​ធ្វើ​សមកាលកម្ម ទៅ​ឯកសារ​មួយ ។
+Comment[lt]=Šis kanalas įrašo informaciją apie delninuką ir sinchronizavimą į bylą.
+Comment[ms]=Saluran ini menulis maklumat tentang komputer telapak dan segerakan ke fail.
+Comment[nb]=Denne kanalen skriver informasjon om PDA-en og synkroniseringen til en fil.
+Comment[nds]=De Kanaal schrifft Informatschonen över den Handreekner un de Synkroniseren na en Datei.
+Comment[ne]=यो कनà¥à¤¡à¥à¤¯à¥à¤Ÿà¤²à¥‡ हà¥à¤¯à¤¾à¤¨à¥à¤¡à¤¹à¥‡à¤²à¥à¤¡ बारेमा सूचना लेखà¥à¤¦à¤› र फाइलमा सिनà¥à¤• गरà¥à¤¦à¤› ।
+Comment[nl]=Dit conduit slaat informatie over uw handheld en de synchronisatie op in een bestand.
+Comment[nn]=Denne koplinga skriv informasjon om den handheldte eininga di og synkroniseringa til ei fil.
+Comment[pl]=Ten Å‚Ä…cznik zapisuje informacje o twoim palmtopie i przebiegu synchronizacji do pliku.
+Comment[pt]=Esta conduta escreve informações sobre o seu dispositivo e a sincronização para um ficheiro.
+Comment[pt_BR]=Este conduíte escreve informação sobre o seu handheld e a sincronização em um arquivo.
+Comment[ru]=Канал передачи ÑиÑтемной информации Ñ ÐšÐŸÐš и запиÑи в файл.
+Comment[sk]=Táto spojka zobrazuje informácie o vašom prenosnom zariadení a ukladá ich do súboru.
+Comment[sl]=Ta veznik zapiÅ¡e podatke o vaÅ¡em roÄnem raÄunalniku in usklajevanju v datoteko.
+Comment[sr]=Овај провод запиÑује информације о вашем ручном рачунару и Ñинхронизује Ñа фајлом.
+Comment[sr@Latn]=Ovaj provod zapisuje informacije o vaÅ¡em ruÄnom raÄunaru i sinhronizuje sa fajlom.
+Comment[sv]=Den här kanalen skriver information om handdatorn och synkroniseringen till en fil.
+Comment[ta]=இநà¯à®¤ காபà¯à®ªà¯à®•à¯ கà¯à®´à®¾à®¯à¯ உஙà¯à®•à®³à¯ கையேடà¯à®Ÿà¯ˆà®ªà¯ பறà¯à®±à®¿à®¯ தகவலà¯à®•à®³à¯ˆà®¯à¯à®®à¯ ஒதà¯à®¤à®¿à®šà¯ˆà®µà¯ˆà®¯à¯à®®à¯ கோபà¯à®ªà¯à®•à¯à®•à¯ எழà¯à®¤à¯à®•à®¿à®±à®¤à¯
+Comment[tg]=Канали таҳвили иттилооти ÑиÑтемавӣ аз Pilot ва қайдкунӣ ба файл
+Comment[tr]=Bu bileşen, el bilgisayarınızın bilgilerini bir dosyaya yazar.
+Comment[uk]=Цей акведук запиÑує інформацію про кишеньковий приÑтрій Ñ– Ñинхронізацію у файл.
+Comment[zh_CN]=此管é“写入您手æŒè®¾å¤‡çš„ä¿¡æ¯ï¼Œå¹¶åŒæ­¥è‡³ä¸€æ–‡ä»¶ã€‚
+Comment[zh_TW]=此軟體將您的 handheld 資訊寫入檔案。
+Name=System Information
+Name[af]=Stelsel informasie
+Name[ar]=معلومات عن النظام
+Name[be]=СыÑÑ‚ÑÐ¼Ð½Ð°Ñ Ñ–Ð½Ñ„Ð°Ñ€Ð¼Ð°Ñ†Ñ‹Ñ
+Name[bg]=СиÑтемна информациÑ
+Name[br]=Titouroù diwar-benn ar reizhiad
+Name[bs]=Sistemske informacije
+Name[ca]=Sistema d'informació
+Name[cs]=Informace o systému
+Name[cy]=Gwybodaeth Gysawd
+Name[da]=Systeminformation
+Name[de]=System-Information
+Name[el]=ΠληÏοφοÏίες συστήματος
+Name[eo]=Sisteminformoj
+Name[es]=Información del sistema
+Name[et]=Süsteemi info
+Name[eu]=Sistemaren informazioa
+Name[fa]=اطلاعات سیستم
+Name[fi]=Järjestelmätiedot
+Name[fr]=Informations sur le système
+Name[fy]=Systeemynformaasje
+Name[ga]=Faisnéis Córais
+Name[gl]=Información do Sistema
+Name[hi]=तंतà¥à¤° जानकारी
+Name[hu]=Rendszerinformáció
+Name[is]=Kerfisupplýsingar
+Name[it]=Informazioni di sistema
+Name[ja]=システム情報
+Name[ka]=სისტემის ინფáƒáƒ áƒ›áƒáƒªáƒ˜áƒ
+Name[kk]=Жүйелік мәлімет
+Name[km]=áž–áŸážáŸŒáž˜áž¶áž“​អំពី​ប្រពáŸáž“្ធ
+Name[lt]=Sistemos informacija
+Name[mk]=Информации за ÑиÑтемот
+Name[ms]=Maklumat Sistem
+Name[nb]=Systeminformasjon
+Name[nds]=Systeem-Informatschoon
+Name[ne]=पà¥à¤°à¤£à¤¾à¤²à¥€ सूचना
+Name[nl]=Systeeminformatie
+Name[nn]=Systeminformasjon
+Name[pl]=Informacja systemowa
+Name[pt]=Informação do Sistema
+Name[pt_BR]=Informação do Sistema
+Name[ro]=Informaţii de sistem
+Name[ru]=Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ ÑиÑтеме
+Name[se]=Vuogádatdieđut
+Name[sk]=Informácie o systéme
+Name[sl]=Sistemske informacije
+Name[sr]=Информације о ÑиÑтему
+Name[sr@Latn]=Informacije o sistemu
+Name[sv]=Systeminformation
+Name[ta]=அமைபà¯à®ªà¯ தகவலà¯
+Name[tg]=Иттилоот дар бораи ÑиÑтема
+Name[tr]=Sistem Bilgisi
+Name[uk]=СиÑтемна інформаціÑ
+Name[uz]=Tizim haqida maʼlumot
+Name[uz@cyrillic]=Тизим ҳақида маълумот
+Name[zh_CN]=系统信æ¯
+Name[zh_TW]=系統資訊
+Implemented=file
+ServiceTypes=KPilotConduit
+X-KDE-Library=conduit_sysinfo
diff --git a/kpilot/conduits/sysinfoconduit/sysinfoconduit.kcfg b/kpilot/conduits/sysinfoconduit/sysinfoconduit.kcfg
new file mode 100644
index 000000000..20d8cc24d
--- /dev/null
+++ b/kpilot/conduits/sysinfoconduit/sysinfoconduit.kcfg
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
+ http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
+ <kcfgfile name="kpilot_sysinfoconduitrc"/>
+ <group name="General">
+ <entry name="OutputFile" key="Output file" type="Path">
+ <default>$HOME/kpilot-syslog.html</default>
+ </entry>
+ <entry name="OutputFormat" key="Output format" type="Enum">
+ <choices>
+ <choice name="eSysInfoHTML"/>
+ <choice name="eSysInfoText"/>
+ <choice name="eSysInfoTemplate"/>
+ </choices>
+ <default>eSysInfoHTML</default>
+ </entry>
+ <entry name="TemplateFile" key="Template file" type="Path">
+ <default></default>
+ </entry>
+ <entry name="DebugInformation" key="Debug Information" type="Bool">
+ <label>Debug information (for KPilot developers)</label>
+ <default>true</default>
+ </entry>
+ <entry name="HardwareInfo" key="Hardware Info" type="Bool">
+ <label>Hardware information</label>
+ <default>true</default>
+ </entry>
+ <entry name="DatabaseList" key="Database List" type="Bool">
+ <label>List of databases on handheld (takes long!)</label>
+ <default>true</default>
+ </entry>
+ <entry name="MemoryInfo" key="Memory Info" type="Bool">
+ <label>Memory information</label>
+ <default>true</default>
+ </entry>
+ <entry name="RecordNumbers" key="Record Numbers" type="Bool">
+ <label>Number of addresses, todos, events and memos</label>
+ <default>true</default>
+ </entry>
+ <entry name="PalmOSVersion" key="PalmOS Version" type="Bool">
+ <label>PalmOS version</label>
+ <default>true</default>
+ </entry>
+ <entry name="StorageInfo" key="Storage Info" type="Bool">
+ <label>Storage info (SD card, memory stick, ...)</label>
+ <default>true</default>
+ </entry>
+ <entry name="SyncInfo" key="Sync Info" type="Bool">
+ <label>Synchronization information</label>
+ <default>true</default>
+ </entry>
+ <entry name="UserInfo" key="User Info" type="Bool">
+ <label>User information</label>
+ <default>true</default>
+ </entry>
+ <entry name="KDEVersion" key="KDE Version" type="Bool">
+ <label>Version of KPilot, pilot-link and KDE</label>
+ <default>true</default>
+ </entry>
+ </group>
+
+</kcfg>
diff --git a/kpilot/conduits/timeconduit/CMakeLists.txt b/kpilot/conduits/timeconduit/CMakeLists.txt
new file mode 100644
index 000000000..e980e724f
--- /dev/null
+++ b/kpilot/conduits/timeconduit/CMakeLists.txt
@@ -0,0 +1,44 @@
+include_directories(
+ ${CMAKE_CURRENT_BINARY_DIR}
+)
+
+set(conduit_time_SRCS
+ time-conduit.cc
+ time-factory.cc
+ time-setup.cc
+)
+
+set(conduit_time_UIS
+ time-setup_dialog.ui
+)
+
+set(conduit_time_KCFGS
+ timeConduitSettings.kcfgc
+)
+
+kde3_add_kcfg_files(conduit_time_SRCS ${conduit_time_KCFGS})
+kde3_add_ui_files(conduit_time_SRCS ${conduit_time_UIS})
+kde3_automoc(${conduit_time_SRCS})
+add_library(conduit_time SHARED ${conduit_time_SRCS})
+
+kpilot_rpath(conduit_time)
+
+set_target_properties(
+ conduit_time PROPERTIES LOCATION ${KDE3_PLUGIN_INSTALL_DIR}
+ PREFIX ""
+)
+
+kde3_install_libtool_file(conduit_time)
+
+install(
+ TARGETS conduit_time
+ LIBRARY DESTINATION ${KDE3_PLUGIN_INSTALL_DIR}
+)
+
+install(
+ FILES time_conduit.desktop DESTINATION ${KDE3_SERVICES_DIR}
+)
+
+install(
+ FILES timeconduit.kcfg DESTINATION ${KDE3_KCFG_DIR}
+)
diff --git a/kpilot/conduits/timeconduit/Makefile.am b/kpilot/conduits/timeconduit/Makefile.am
new file mode 100644
index 000000000..6a58716a5
--- /dev/null
+++ b/kpilot/conduits/timeconduit/Makefile.am
@@ -0,0 +1,22 @@
+### Makefile for the time conduit
+###
+### The time conduit is Copyright (C) 2002 by Reinhold Kainhofer
+
+INCLUDES= $(PISOCK_INCLUDE) -I$(top_srcdir)/kpilot/lib $(all_includes)
+METASOURCES = AUTO
+
+servicedir = $(kde_servicesdir)
+service_DATA = time_conduit.desktop
+
+kde_module_LTLIBRARIES = conduit_time.la
+
+
+conduit_time_la_SOURCES = timeConduitSettings.kcfgc \
+ time-factory.cc \
+ time-setup.cc \
+ time-conduit.cc \
+ time-setup_dialog.ui
+conduit_time_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries)
+conduit_time_la_LIBADD = ../../lib/libkpilot.la $(LIB_KDEUI)
+
+kde_kcfg_DATA = timeconduit.kcfg
diff --git a/kpilot/conduits/timeconduit/time-conduit.cc b/kpilot/conduits/timeconduit/time-conduit.cc
new file mode 100644
index 000000000..c1455b359
--- /dev/null
+++ b/kpilot/conduits/timeconduit/time-conduit.cc
@@ -0,0 +1,121 @@
+/* KPilot
+**
+** Copyright (C) 2002-2003 by Reinhold Kainhofer
+**
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org.
+*/
+
+#include "options.h"
+
+#include <time.h>
+
+#include <pilotSysInfo.h>
+
+#include <kconfig.h>
+#include <kdebug.h>
+
+#include "time-factory.h"
+#include "time-conduit.h"
+#include "timeConduitSettings.h"
+
+
+// Something to allow us to check what revision
+// the modules are that make up a binary distribution.
+extern "C"
+{
+unsigned long version_conduit_time = Pilot::PLUGIN_API ;
+}
+
+
+
+TimeConduit::TimeConduit(KPilotLink * o,
+ const char *n,
+ const QStringList & a) :
+ ConduitAction(o, n, a)
+{
+ FUNCTIONSETUP;
+ fConduitName=i18n("Time");
+}
+
+
+
+TimeConduit::~TimeConduit()
+{
+ FUNCTIONSETUP;
+}
+
+
+
+void TimeConduit::readConfig()
+{
+ FUNCTIONSETUP;
+ TimeConduitSettings::self()->readConfig();
+}
+
+
+/* virtual */ bool TimeConduit::exec()
+{
+ FUNCTIONSETUP;
+
+ readConfig();
+
+ if (syncMode().isLocal())
+ {
+#ifdef DEBUG
+ DEBUGKPILOT << fname << ": Would have set time to "
+ << QDateTime::currentDateTime().toString() << endl;
+#endif
+ return delayDone();
+ }
+
+ emit logMessage(i18n("Setting the clock on the handheld"));
+ syncHHfromPC();
+ return delayDone();
+}
+
+
+void TimeConduit::syncHHfromPC()
+{
+ FUNCTIONSETUP;
+ time_t ltime;
+ time(&ltime);
+
+ long int major=fHandle->getSysInfo().getMajorVersion(),
+ minor=fHandle->getSysInfo().getMinorVersion();
+
+ if (major==3 && (minor==25 || minor==30))
+ {
+ emit logMessage(i18n("PalmOS 3.25 and 3.3 do not support setting the system time. Skipping the time conduit..."));
+ return;
+ }
+
+ int sd = pilotSocket();
+ if ( sd > 0 )
+ {
+ dlp_SetSysDateTime( sd, ltime );
+ }
+ else
+ {
+ WARNINGKPILOT << "Link is not a real device." << endl;
+ }
+}
diff --git a/kpilot/conduits/timeconduit/time-conduit.h b/kpilot/conduits/timeconduit/time-conduit.h
new file mode 100644
index 000000000..8a6a57a50
--- /dev/null
+++ b/kpilot/conduits/timeconduit/time-conduit.h
@@ -0,0 +1,49 @@
+#ifndef _Time_CONDUIT_H
+#define _Time_CONDUIT_H
+/* time-conduit.h KPilot
+**
+** Copyright (C) 2002 by Reinhold Kainhofer
+**
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+
+#include <plugin.h>
+
+class TimeConduit : public ConduitAction
+{
+public:
+ TimeConduit(
+ KPilotLink *o,
+ const char *n = 0L,
+ const QStringList &a = QStringList() );
+ virtual ~TimeConduit();
+ virtual bool exec();
+
+ void syncHHfromPC();
+
+protected:
+ void readConfig();
+} ;
+
+#endif
diff --git a/kpilot/conduits/timeconduit/time-factory.cc b/kpilot/conduits/timeconduit/time-factory.cc
new file mode 100644
index 000000000..28548fe50
--- /dev/null
+++ b/kpilot/conduits/timeconduit/time-factory.cc
@@ -0,0 +1,46 @@
+/* Time-factory.cc KPilot
+**
+** Copyright (C) 2002 by Reinhold Kainhofer
+**
+** This file defines the factory for the Time-conduit plugin.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include "options.h"
+#include "pluginfactory.h"
+
+#include "time-conduit.h"
+#include "time-setup.h"
+
+
+extern "C"
+{
+
+void *init_conduit_time()
+{
+ return new ConduitFactory<TimeWidgetConfig,TimeConduit>(0,"Timeconduit");
+}
+
+}
+
+
diff --git a/kpilot/conduits/timeconduit/time-factory.h b/kpilot/conduits/timeconduit/time-factory.h
new file mode 100644
index 000000000..2b53c7c11
--- /dev/null
+++ b/kpilot/conduits/timeconduit/time-factory.h
@@ -0,0 +1,41 @@
+#ifndef _TIME_FACTORY_H
+#define _TIME_FACTORY_H
+/* Time-factory.h KPilot
+**
+** Copyright (C) 2002 by Reinhold Kainhofer
+**
+** This file defines the factory for the Time-conduit plugin.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#define DIR_PCToPalm 0
+#define DIR_PalmToPC 1
+
+extern "C"
+{
+
+void *init_conduit_time();
+
+}
+
+#endif
diff --git a/kpilot/conduits/timeconduit/time-setup.cc b/kpilot/conduits/timeconduit/time-setup.cc
new file mode 100644
index 000000000..ce562d7dd
--- /dev/null
+++ b/kpilot/conduits/timeconduit/time-setup.cc
@@ -0,0 +1,86 @@
+/* Time-setup.cc KPilot
+**
+** Copyright (C) 2002 by Reinhold Kainhofer
+**
+** This file defines the setup dialog for the Time-conduit plugin.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include "options.h"
+
+#include <qtabwidget.h>
+#include <qradiobutton.h>
+#include <qbuttongroup.h>
+
+#include <kapplication.h>
+#include <kaboutdata.h>
+
+#include "time-setup_dialog.h"
+
+#include "time-setup.moc"
+#include "timeConduitSettings.h"
+
+
+
+static KAboutData *createAbout()
+{
+ KAboutData *fAbout = new KAboutData("Timeconduit",
+ I18N_NOOP("Time Synchronization Conduit for KPilot"),
+ KPILOT_VERSION,
+ I18N_NOOP("Synchronizes the Time on the Handheld and the PC"),
+ KAboutData::License_GPL,
+ "(C) 2002, Reinhold Kainhofer");
+ fAbout->addAuthor("Reinhold Kainhofer",
+ I18N_NOOP("Primary Author"), "reinhold@kainhofer.com", "http://reinhold.kainhofer.com/");
+ return fAbout;
+}
+
+
+
+TimeWidgetConfig::TimeWidgetConfig(QWidget *w, const char *n) :
+ ConduitConfigBase(w,n),
+ fConfigWidget(new TimeWidget(w))
+{
+ FUNCTIONSETUP;
+ fAbout = createAbout();
+ ConduitConfigBase::addAboutPage(fConfigWidget->tabWidget,fAbout);
+ fWidget=fConfigWidget;
+ fConduitName=i18n("Time");
+}
+
+void TimeWidgetConfig::commit()
+{
+ FUNCTIONSETUP;
+ TimeConduitSettings::setDirection(
+ fConfigWidget->directionGroup->id(fConfigWidget->directionGroup->selected()) );
+ TimeConduitSettings::self()->writeConfig();
+}
+
+void TimeWidgetConfig::load()
+{
+ FUNCTIONSETUP;
+ TimeConduitSettings::self()->readConfig();
+
+ fConfigWidget->directionGroup->setButton( TimeConduitSettings::direction() );
+}
+
diff --git a/kpilot/conduits/timeconduit/time-setup.h b/kpilot/conduits/timeconduit/time-setup.h
new file mode 100644
index 000000000..7552c12d6
--- /dev/null
+++ b/kpilot/conduits/timeconduit/time-setup.h
@@ -0,0 +1,50 @@
+#ifndef _Time_Time_SETUP_H
+#define _Time_Time_SETUP_H
+/* knotes-setup.h KPilot
+**
+** Copyright (C) 2002 by Reinhold Kainhofer
+**
+** This file defines the widget and behavior for the config dialog
+** of the KNotes conduit.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include "plugin.h"
+
+class TimeWidget;
+class KAboutData;
+
+class TimeWidgetConfig : public ConduitConfigBase
+{
+Q_OBJECT
+public:
+ TimeWidgetConfig(QWidget *parent, const char *);
+ virtual void commit();
+ virtual void load();
+ static ConduitConfigBase *create(QWidget *,const char *);
+protected:
+ TimeWidget *fConfigWidget;
+ KAboutData *fAbout;
+} ;
+
+#endif
diff --git a/kpilot/conduits/timeconduit/time-setup_dialog.ui b/kpilot/conduits/timeconduit/time-setup_dialog.ui
new file mode 100644
index 000000000..b419b9250
--- /dev/null
+++ b/kpilot/conduits/timeconduit/time-setup_dialog.ui
@@ -0,0 +1,122 @@
+<!DOCTYPE UI><UI version="3.0" stdsetdef="1">
+<class>TimeWidget</class>
+<author>Reinhold Kainhofer</author>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>Form2</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>399</width>
+ <height>293</height>
+ </rect>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QTabWidget" row="0" column="0">
+ <property name="name">
+ <cstring>tabWidget</cstring>
+ </property>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>General</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <spacer row="2" column="0">
+ <property name="name">
+ <cstring>Spacer3</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ </spacer>
+ <widget class="QButtonGroup" row="0" column="0">
+ <property name="name">
+ <cstring>directionGroup</cstring>
+ </property>
+ <property name="title">
+ <string>Direction</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QRadioButton" row="0" column="0">
+ <property name="name">
+ <cstring>RadioButton1</cstring>
+ </property>
+ <property name="text">
+ <string>Set the &amp;handheld time from the time on the PC</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Select this option to synchronize the handheld time with the PC time, by using the PC time on both.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="1" column="0">
+ <property name="name">
+ <cstring>RadioButton1_2</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Set the &amp;PC time from the time on the handheld</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Select this option to synchronize the handheld time with the PC time, by using the handheld time on both.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>TextLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>&lt;qt&gt;PalmOS Version 3.25 and 3.3 do not support setting the system time, so this conduit will be skipped for handhelds that run either of these operating systems.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </widget>
+ </grid>
+</widget>
+<tabstops>
+ <tabstop>tabWidget</tabstop>
+</tabstops>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/kpilot/conduits/timeconduit/timeConduitSettings.kcfgc b/kpilot/conduits/timeconduit/timeConduitSettings.kcfgc
new file mode 100644
index 000000000..3487b6a68
--- /dev/null
+++ b/kpilot/conduits/timeconduit/timeConduitSettings.kcfgc
@@ -0,0 +1,7 @@
+File=timeconduit.kcfg
+ClassName=TimeConduitSettings
+Singleton=true
+ItemAccessors=true
+Mutators=true
+GlobalEnums=true
+SetUserTexts=true
diff --git a/kpilot/conduits/timeconduit/time_conduit.desktop b/kpilot/conduits/timeconduit/time_conduit.desktop
new file mode 100644
index 000000000..cbdafc9f4
--- /dev/null
+++ b/kpilot/conduits/timeconduit/time_conduit.desktop
@@ -0,0 +1,107 @@
+[Desktop Entry]
+Type=Service
+Comment=This conduit sets the time on your handheld from the PC clock.
+Comment[af]=Hierdie pad stel die tyd op jou draagbare toestel vanaf die PC horlosie.
+Comment[bg]=Ð¡Ð¸Ð½Ñ…Ñ€Ð¾Ð½Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð½Ð° датата и чаÑа на мобилно уÑтройÑтво Ñ Ñ‡Ð°Ñовника на компютъра
+Comment[bs]=Ovaj conduit postavlja vrijeme na vaÅ¡em ruÄnom raÄunaru prema PC satu.
+Comment[ca]=Aquest conducte estableix l'hora en la vostra agenda electrònica des del rellotge del PC.
+Comment[cs]=Toto propojení nastaví Äas na vaÅ¡em handheldu podle PC.
+Comment[cy]=Mae'r cwndid yma yn gosod yr amser ar eich llawiadur o gloc y CP.
+Comment[da]=Denne kanal sætter tiden på din håndholdte fra PC'ens ur.
+Comment[de]=Überträgt die Zeit vom PC auf das mobile Gerät
+Comment[el]=Αυτός ο σÏνδεσμος Ïυθμίζει την ÏŽÏα στον υπολογιστή παλάμης σας από το Ïολόι του υπολογιστή σας.
+Comment[es]=Este conducto fija la hora de su agenda electrónica según el reloj de su PC.
+Comment[et]=See kanal sünkroniseerib pihuarvuti aja PC kellaga.
+Comment[eu]=Kanal honek zure agenda elektronikoko ordua PC-aren ordura ezartzen du.
+Comment[fa]=این لوله، از طریق ساعت PC زمان دستی شما را تنظیم می‌کند.
+Comment[fi]=Tämä yhdyskäytävä asettaa taskutietokoneen kellonajan PC:n kellosta.
+Comment[fr]=Ce canal règle l'heure de votre périphérique depuis celle du PC.
+Comment[fy]=Dit conduit set de tiid fan jo handheld oan d ehân fan de pc-klok.
+Comment[gl]=Este conducto pon a hora do seu aparello portátil dende o reloxo do seu PC.
+Comment[hi]=यह कनà¥à¤¡à¥à¤¯à¥‚इट आपके हैंणà¥à¤¡à¤¹à¥‡à¤²à¥à¤¡ में पीसी घड़ी दà¥à¤µà¤¾à¤°à¤¾ समय नियत करता है.
+Comment[hu]=Ez a csatoló beállítja a kéziszámítógép óráját a számítógépé alapján
+Comment[is]=Þessi rás stillir klukku lófatölvunnar eftir klukku PC tölvunnar.
+Comment[it]=Questo conduit imposta l'ora sul tuo palmare prendendola dall'orologio del PC
+Comment[ja]=ã“ã®ã‚³ãƒ³ã‚¸ãƒƒãƒˆã¯ãƒãƒ³ãƒ‰ãƒ˜ãƒ«ãƒ‰ã®æ™‚é–“ã‚’PCã®æ™‚計ã«åˆã‚ã›ã¾ã™ã€‚
+Comment[ka]=დრáƒáƒ˜áƒ¡ მითითებრკáƒáƒ›áƒžáƒ˜áƒ£áƒ¢áƒ”რის სáƒáƒáƒ—ისთვის.
+Comment[km]=បំពង់​នáŸáŸ‡â€‹áž€áŸ†ážŽážáŸ‹â€‹áž–áŸáž›ážœáŸáž›áž¶â€‹áž“ៅ​លើ​ឧបករណáŸâ€‹áž™áž½ážšážŠáŸƒâ€‹ážšáž”ស់​អ្នក ពី​នាឡិកា​កុំព្យូទáŸážšÂ áŸ”
+Comment[lt]=Å is kanalas nustato delninuko laikÄ… pagal PC laikÄ….
+Comment[mk]=Овој канал го поÑтавува времето на рачниот уред Ñпоред времето на компјутерот.
+Comment[ms]=Saluran ini mengeset waktu pada komputer telapak anda dari jam PC.
+Comment[nb]=Denne kanalen stiller klokka på PDA-en fra PC-klokka.
+Comment[nds]=Synkroniseert stellt Handreekner-Klock na de PC-Klock.
+Comment[ne]=यो कनà¥à¤¡à¥à¤¯à¥à¤Ÿà¤²à¥‡ पीसी घडीबाट हà¥à¤¯à¤¾à¤¨à¥à¤¡à¤¹à¥‡à¤²à¥à¤¡à¤®à¤¾ समय सेट गरà¥à¤¦à¤› ।
+Comment[nl]=Dit conduit stelt de tijd van uw handheld in aan de hand van de pc-klok.
+Comment[nn]=Denne koplinga set tida på den handheldte eininga di frå PC-klokka.
+Comment[pl]=Ten Å‚Ä…cznik ustawia zegar na palmtopie zgodnie z zegarem komputera.
+Comment[pt]=Esta conduta acerta a hora do seu dispositivo a partir do relógio do PC.
+Comment[pt_BR]=Este conduíte define o horário no seu hendheld a partir do relógio do PC.
+Comment[ru]=Канал Ñинхронизации времени
+Comment[sk]=Táto spojka nastavuje Äas na vaÅ¡om prenosnom zariadení podľa PC.
+Comment[sl]=Ta veznik nastavi Äas na roÄnem raÄunalniku glede na sistemsko uro osebnega raÄunalnika.
+Comment[sr]=Овај провод поÑтавља време на вашем ручном рачунару према PC чаÑовнику.
+Comment[sr@Latn]=Ovaj provod postavlja vreme na vaÅ¡em ruÄnom raÄunaru prema PC Äasovniku.
+Comment[sv]=Den här kanalen ställer in tiden på handdatorn från datorns klocka.
+Comment[ta]=இநà¯à®¤ காபà¯à®ªà¯à®•à¯à®•à¯à®´à®¾à®¯à¯ பிசி கடிகாரதà¯à®¤à®¿à®²à¯ இரà¯à®¨à¯à®¤à¯ உஙà¯à®•à®³à¯ கையேடà¯à®Ÿà®¿à®²à¯ நேரதà¯à®¤à¯ˆ அமைகà¯à®•à¯à®®à¯
+Comment[tg]=Канали ÑинзронизатÑиÑи муддат
+Comment[tr]=Bu bileşen, el bilgisayarınızın saatini PC saatine bakarak ayarlar.
+Comment[uk]=Цей акведук Ñинхронізує Ñ‡Ð°Ñ Ñƒ кишеньковому приÑтрої з чаÑом комп'ютера.
+Comment[zh_CN]=此管é“把您手æŒè®¾å¤‡çš„时间与电脑åŒæ­¥ã€‚
+Comment[zh_TW]=此軟體經由 PC 時間設定您的 handheld 時間。
+Name=Time Synchronization
+Name[af]=Tyd sinkronisasie
+Name[ar]=مزامنة الوقت
+Name[be]=Ð¡Ñ‹Ð½Ñ…Ñ€Ð°Ð½Ñ–Ð·Ð°Ñ†Ñ‹Ñ Ñ‡Ð°Ñу
+Name[bg]=СинхронизациÑ
+Name[bs]=Sinhronizacija vremena
+Name[ca]=Sincronització horària
+Name[cs]=Synchronizace Äasu
+Name[cy]=Cydamseriad Amser
+Name[da]=Tidsynkronisering
+Name[de]=Zeit-Abgleich
+Name[el]=ΣυγχÏονισμός ÏŽÏας
+Name[en_GB]=Time Synchronisation
+Name[eo]=Temposinkronigo
+Name[es]=Sincronización de hora
+Name[et]=Aja sünkroniseerimine
+Name[eu]=Ordu sinkronizazioa
+Name[fa]=همگام‌سازی زمان
+Name[fi]=Ajan synkronointi
+Name[fr]=Synchronisation de l'heure
+Name[fy]=Tiidssyngronisaasje
+Name[gl]=Sincronización Horaria
+Name[hi]=समय सिंकà¥à¤°à¥‹à¤¨à¤¾à¤‡à¤œà¤¼à¥‡à¤¶à¤¨
+Name[hu]=Időszinkronizálás
+Name[is]=Tíma samstilling
+Name[it]=Sincronizzazione temporale
+Name[ja]=時間åŒæœŸ
+Name[ka]=დრáƒáƒ˜áƒ¡ სინქრáƒáƒœáƒ˜áƒ–áƒáƒªáƒ˜áƒ
+Name[kk]=Уақытты қадамдаÑтыру
+Name[km]=សមកាលកម្ម​ពáŸáž›ážœáŸáž›áž¶
+Name[lt]=Laiko sinchronizavimas
+Name[mk]=Синхронизација на време
+Name[ms]=Segerakan waktu
+Name[nb]=Tidsynkronisering
+Name[nds]=Tietsynkroniseren
+Name[ne]=समय समकà¥à¤°à¤®à¤£
+Name[nl]=Tijdsynchronisatie
+Name[nn]=Tidsynkronisering
+Name[pl]=Synchronizacja czasu
+Name[pt]=Sincronização Horária
+Name[pt_BR]=Sincronização de Horário
+Name[ro]=Sincronizare timp
+Name[ru]=Ð¡Ð¸Ð½Ñ…Ñ€Ð¾Ð½Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð²Ñ€ÐµÐ¼ÐµÐ½Ð¸
+Name[sk]=Synchronizácia Äasu
+Name[sl]=Usklajevanje Äasa
+Name[sr]=Синхронизација времена
+Name[sr@Latn]=Sinhronizacija vremena
+Name[sv]=Tidssynkronisering
+Name[ta]=நேர ஒதà¯à®¤à®¿à®¯à®•à¯à®•à®®à¯
+Name[tg]=СинхронизатÑиÑи муддат
+Name[tr]=Zaman Senkronizasyonu
+Name[uk]=Ð¡Ð¸Ð½Ñ…Ñ€Ð¾Ð½Ñ–Ð·Ð°Ñ†Ñ–Ñ Ñ‡Ð°Ñу
+Name[zh_CN]=时间åŒæ­¥
+Name[zh_TW]=時刻åŒæ­¥åŒ–
+Implemented=file
+ServiceTypes=KPilotConduit
+X-KDE-Library=conduit_time
diff --git a/kpilot/conduits/timeconduit/timeconduit.kcfg b/kpilot/conduits/timeconduit/timeconduit.kcfg
new file mode 100644
index 000000000..aafa23fc9
--- /dev/null
+++ b/kpilot/conduits/timeconduit/timeconduit.kcfg
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
+ http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
+ <kcfgfile name="kpilot_timeconduitrc"/>
+ <group name="Time-conduit">
+ <entry name="Direction" type="Enum">
+ <choices>
+ <choice name="eSetHHfromPC"/>
+ <choice name="eSetPCfromHH"/>
+ </choices>
+ <default>eSetHHfromPC</default>
+ </entry>
+ </group>
+
+</kcfg>
diff --git a/kpilot/conduits/vcalconduit/CMakeLists.txt b/kpilot/conduits/vcalconduit/CMakeLists.txt
new file mode 100644
index 000000000..21482355f
--- /dev/null
+++ b/kpilot/conduits/vcalconduit/CMakeLists.txt
@@ -0,0 +1,75 @@
+set(conduit_LIBS kcal)
+
+include_directories(
+ ${CMAKE_CURRENT_BINARY_DIR}
+)
+
+set(conduit_SHARED
+ vcal-setupbase.cc
+ vcal-conduitbase.cc
+ teststate.cc
+ initstate.cc
+ pctohhstate.cc
+ hhtopcstate.cc
+ cleanupstate.cc
+ deleteunsyncedpcstate.cc
+ deleteunsyncedhhstate.cc
+ kcalRecord.cc
+ vcalRecord.cc
+ todoRecord.cc
+)
+
+kde3_add_kcfg_files(conduit_SHARED vcalconduitSettings.kcfgc)
+kde3_add_ui_files(conduit_SHARED korganizerConduit.ui)
+
+set(conduit_vcal_SRCS
+ ${conduit_SHARED}
+ vcal-conduit.cc
+ vcal-factory.cc
+ vcal-setup.cc
+)
+
+kde3_automoc(${conduit_vcal_SRCS})
+add_library(conduit_vcal SHARED ${conduit_vcal_SRCS})
+target_link_libraries(conduit_vcal kcal)
+
+set(conduit_todo_SRCS
+ ${conduit_SHARED}
+ todo-factory.cc
+ todo-setup.cc
+ todo-conduit.cc
+)
+
+kde3_automoc(${conduit_todo_SRCS})
+add_library(conduit_todo SHARED ${conduit_todo_SRCS})
+target_link_libraries(conduit_todo kcal)
+
+set_target_properties(
+ conduit_vcal PROPERTIES LOCATION ${KDE3_PLUGIN_INSTALL_DIR}
+ INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/lib
+ PREFIX ""
+)
+set_target_properties(
+ conduit_todo PROPERTIES LOCATION ${KDE3_PLUGIN_INSTALL_DIR}
+ INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/lib
+ PREFIX ""
+)
+
+kde3_install_libtool_file(conduit_vcal)
+
+install(
+ TARGETS conduit_vcal conduit_todo
+ LIBRARY DESTINATION ${KDE3_PLUGIN_INSTALL_DIR}
+ LIBRARY DESTINATION ${KDE3_PLUGIN_INSTALL_DIR}
+)
+
+kde3_install_libtool_file(conduit_todo)
+
+install(
+ FILES vcal-conduit.desktop todo-conduit.desktop
+ DESTINATION ${KDE3_SERVICES_DIR}
+)
+
+install(
+ FILES vcalconduitbase.kcfg DESTINATION ${KDE3_KCFG_DIR}
+)
diff --git a/kpilot/conduits/vcalconduit/Makefile.am b/kpilot/conduits/vcalconduit/Makefile.am
new file mode 100644
index 000000000..546789e17
--- /dev/null
+++ b/kpilot/conduits/vcalconduit/Makefile.am
@@ -0,0 +1,43 @@
+###
+### Makefile for vcal and todo conduits. These two conduits share most code,
+### so it seems logical to put them in one place.
+###
+
+INCLUDES= -I$(top_srcdir)/kpilot/lib -I$(top_srcdir) \
+ $(PISOCK_INCLUDE) $(all_includes)
+
+METASOURCES = AUTO
+
+servicedir = $(kde_servicesdir)
+service_DATA = vcal-conduit.desktop todo-conduit.desktop
+
+kde_module_LTLIBRARIES = conduit_vcal.la conduit_todo.la
+noinst_LTLIBRARIES = libvcalconduit_shared.la
+
+libvcalconduit_shared_la_SOURCES = vcalconduitSettings.kcfgc \
+ korganizerConduit.ui \
+ kcalRecord.cc \
+ vcal-setupbase.cc \
+ vcal-conduitbase.cc \
+ cleanupstate.cc deleteunsyncedhhstate.cc deleteunsyncedpcstate.cc \
+ hhtopcstate.cc initstate.cc pctohhstate.cc teststate.cc
+
+conduit_vcal_la_SOURCES = vcal-conduit.cc vcalRecord.cc \
+ vcal-factory.cc vcal-setup.cc
+conduit_vcal_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries)
+conduit_vcal_la_LIBADD = ../../lib/libkpilot.la \
+ ../../../libkcal/libkcal.la \
+ libvcalconduit_shared.la
+conduit_vcal_la_COMPILE_FIRST = vcalconduitSettings.h korganizerConduit.h
+
+conduit_todo_la_SOURCES = todo-conduit.cc todoRecord.cc \
+ todo-factory.cc todo-setup.cc
+conduit_todo_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries)
+conduit_todo_la_LIBADD = ../../lib/libkpilot.la \
+ ../../../libkcal/libkcal.la \
+ libvcalconduit_shared.la
+conduit_todo_la_COMPILE_FIRST = vcalconduitSettings.h korganizerConduit.h
+
+
+kde_kcfg_DATA = vcalconduitbase.kcfg
+
diff --git a/kpilot/conduits/vcalconduit/README b/kpilot/conduits/vcalconduit/README
new file mode 100644
index 000000000..8d4ea49ab
--- /dev/null
+++ b/kpilot/conduits/vcalconduit/README
@@ -0,0 +1,11 @@
+KPilot vCal KOrganizer conduit version 3.0
+(c) 1998 Dan Pilone, Preston Brown, Herwin Jan Steehouwer
+
+This conduit works with KPilot and KOrganizer.
+
+Things to remember:
+* When deleting from yout PalmPilot set
+ 'Save Archive Copy On PC' OFF !!!
+
+Preston Brown and Herwin Jan Steehouwer
+pbrown@kde.org, steehouwer@kde.org
diff --git a/kpilot/conduits/vcalconduit/cleanupstate.cc b/kpilot/conduits/vcalconduit/cleanupstate.cc
new file mode 100644
index 000000000..29b1f6ea5
--- /dev/null
+++ b/kpilot/conduits/vcalconduit/cleanupstate.cc
@@ -0,0 +1,132 @@
+/* KPilot
+**
+** Copyright (C) 2006 by Bertjan Broeksema <b.broeksema@gmail.com>
+**
+** This file is the implementation of the CleanUpState.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include <options.h>
+
+#include <kio/netaccess.h>
+#include <qfile.h>
+
+#include "pilotDatabase.h"
+
+#include "vcal-conduitbase.h"
+#include "vcalconduitSettings.h"
+#include "cleanupstate.h"
+
+
+CleanUpState::CleanUpState()
+{
+ fState = eCleanUp;
+}
+
+CleanUpState::~CleanUpState()
+{
+}
+
+void CleanUpState::startSync( ConduitAction *ca )
+{
+ FUNCTIONSETUP;
+
+ VCalConduitBase *vccb = dynamic_cast<VCalConduitBase*>(ca);
+ if( !vccb )
+ {
+ return;
+ }
+
+ DEBUGKPILOT << fname << ": Starting CleanUpState." << endl;
+
+ vccb->addLogMessage( i18n( "Cleaning up ..." ) );
+ vccb->postSync();
+
+ if ( vccb->database() )
+ {
+ vccb->database()->resetSyncFlags();
+ vccb->database()->cleanup();
+ }
+ if ( vccb->localDatabase() )
+ {
+ vccb->localDatabase()->resetSyncFlags();
+ vccb->localDatabase()->cleanup();
+ }
+
+ KCal::Calendar *fCalendar = vccb->calendar();
+ QString fCalendarFile = vccb->calendarFile();
+
+ if ( fCalendar )
+ {
+ KURL kurl( vccb->config()->calendarFile() );
+ switch( vccb->config()->calendarType() )
+ {
+ case VCalConduitSettings::eCalendarLocal:
+ dynamic_cast<KCal::CalendarLocal*>(fCalendar)->save( fCalendarFile );
+ if(!kurl.isLocalFile())
+ {
+ if( !KIO::NetAccess::upload( fCalendarFile
+ , vccb->config()->calendarFile(), 0L) )
+ {
+ vccb->addLogError( i18n( "An error occurred while uploading"
+ " \"%1\". You can try to upload "
+ "the temporary local file \"%2\" manually.")
+ .arg(vccb->config()->calendarFile()).arg(fCalendarFile));
+ }
+ else {
+ KIO::NetAccess::removeTempFile( fCalendarFile );
+ }
+ QFile backup( fCalendarFile + CSL1( "~" ) );
+ backup.remove();
+ }
+ break;
+ case VCalConduitSettings::eCalendarResource:
+ fCalendar->save();
+ break;
+ default:
+ break;
+ }
+ fCalendar->close();
+ }
+
+ vccb->setHasNextRecord( false );
+}
+
+void CleanUpState::handleRecord( ConduitAction * )
+{
+ FUNCTIONSETUP;
+}
+
+void CleanUpState::finishSync( ConduitAction *ca )
+{
+ FUNCTIONSETUP;
+
+ VCalConduitBase *vccb = dynamic_cast<VCalConduitBase*>(ca);
+ if( !vccb )
+ {
+ return;
+ }
+
+ DEBUGKPILOT << fname << ": Finished CleanUpState." << endl;
+ vccb->setState( 0L );
+}
diff --git a/kpilot/conduits/vcalconduit/cleanupstate.h b/kpilot/conduits/vcalconduit/cleanupstate.h
new file mode 100644
index 000000000..4d599cdf7
--- /dev/null
+++ b/kpilot/conduits/vcalconduit/cleanupstate.h
@@ -0,0 +1,49 @@
+#ifndef _KPILOT_CLEANUPSTATE_H
+#define _KPILOT_CLEANUPSTATE_H
+/* cleanupstate.h KPilot
+**
+** Copyright (C) 2006 Bertjan Broeksema
+**
+** This file defines the cleanupstate for vcal-conduitbase.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include "conduitstate.h"
+
+class ConduitAction;
+
+/**
+ * State to Cleanup after all sync actions are finished. @see vcal-conduitstate.h
+ */
+class CleanUpState : public ConduitState
+{
+public:
+ CleanUpState();
+ virtual ~CleanUpState();
+
+ virtual void startSync( ConduitAction* );
+ virtual void handleRecord( ConduitAction* );
+ virtual void finishSync( ConduitAction* );
+};
+
+#endif
diff --git a/kpilot/conduits/vcalconduit/conduitstate.h b/kpilot/conduits/vcalconduit/conduitstate.h
new file mode 100644
index 000000000..447ce1c5a
--- /dev/null
+++ b/kpilot/conduits/vcalconduit/conduitstate.h
@@ -0,0 +1,86 @@
+#ifndef _KPILOT_CONDUITSTATE_H
+#define _KPILOT_CONDUITSTATE_H
+/* vcal-conduitstate.h KPilot
+**
+** Copyright (C) 2006 Bertjan Broeksema
+**
+** This file defines the vcal-conduitstate.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include "plugin.h"
+
+/**
+ * This class defines the current state of the vcal-conduitbase. Subclasses of
+ * this class can do the things that are needed, in methods defined here, for
+ * the state that they define.
+ */
+class ConduitState
+{
+public:
+ enum state_t {
+ eTest,
+ eInit,
+ ePCToHH,
+ eHHToPC,
+ eDeleteUnsyncedHH,
+ eDeleteUnsyncedPC,
+ eCleanUp
+ };
+
+protected:
+ state_t fState;
+ bool fStarted;
+
+public:
+ ConduitState(){ fState = eInit; fStarted = false; };
+ virtual ~ConduitState() {};
+
+ /**
+ * Prepare for a sync in the current state. Don't forget to set fState to
+ * true in this method. Otherwise the state won't handle records.
+ */
+ virtual void startSync( ConduitAction * ) = 0;
+
+ /**
+ * Sync the next record in row.
+ */
+ virtual void handleRecord( ConduitAction * ) = 0;
+
+ /**
+ * Clean up after all records are synced and enter next state.
+ */
+ virtual void finishSync( ConduitAction * ) = 0;
+
+ /**
+ * Returns the state type.
+ */
+ state_t state() { return fState; };
+
+ /**
+ * Returns wether or not this state has started.
+ */
+ bool started() { return fStarted; };
+};
+
+#endif
diff --git a/kpilot/conduits/vcalconduit/deleteunsyncedhhstate.cc b/kpilot/conduits/vcalconduit/deleteunsyncedhhstate.cc
new file mode 100644
index 000000000..78fb67807
--- /dev/null
+++ b/kpilot/conduits/vcalconduit/deleteunsyncedhhstate.cc
@@ -0,0 +1,115 @@
+/* KPilot
+**
+** Copyright (C) 2006 by Bertjan Broeksema <b.broeksema@gmail.com>
+**
+** This file is the implementation of the DeleteUnsyncedHHState.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include <options.h>
+#include <plugin.h>
+
+#include "pilotDatabase.h"
+#include "pilotRecord.h"
+
+#include "vcal-conduitbase.h"
+#include "deleteunsyncedhhstate.h"
+#include "deleteunsyncedpcstate.h"
+#include "cleanupstate.h"
+
+DeleteUnsyncedHHState::DeleteUnsyncedHHState()
+{
+ fState = eDeleteUnsyncedHH;
+}
+
+DeleteUnsyncedHHState::~DeleteUnsyncedHHState()
+{
+}
+
+void DeleteUnsyncedHHState::startSync( ConduitAction *ca )
+{
+ FUNCTIONSETUP;
+
+ VCalConduitBase *vccb = dynamic_cast<VCalConduitBase*>(ca);
+ if( !vccb )
+ {
+ return;
+ }
+
+ DEBUGKPILOT << fname << ": Starting DeleteUnsyncedHHState." << endl;
+
+ fPilotIndex = 0;
+ fNextState = new DeleteUnsyncedPCState();
+
+ vccb->setHasNextRecord( true );
+ fStarted = true;
+}
+
+void DeleteUnsyncedHHState::handleRecord( ConduitAction *ca )
+{
+ FUNCTIONSETUP;
+
+ VCalConduitBase *vccb = dynamic_cast<VCalConduitBase*>(ca);
+ if( !vccb )
+ {
+ return;
+ }
+
+ PilotRecord *r = vccb->localDatabase()->readRecordByIndex( fPilotIndex++ );
+ // if either we don't have a record, or if we're copying everything
+ // from the handheld to the pc, then we don't have anything to do
+ // here. the latter is because if we're copying HH->PC, then by
+ // definition, we will have everything from the HH on the PC and
+ // therefore can't possibly have anything that needs to be deleted
+ // from it.
+ if ( !r
+ || ( vccb->syncMode().mode() == ConduitAction::SyncMode::eCopyHHToPC ) )
+ {
+ vccb->setHasNextRecord( false );
+ return;
+ }
+
+ KCal::Incidence *e = vccb->privateBase()->findIncidence( r->id() );
+ if ( !e )
+ {
+ DEBUGKPILOT << "Didn't find incidence with id = " << r->id()
+ << ", deleting it" << endl;
+ vccb->deletePalmRecord( NULL, r );
+ }
+
+ KPILOT_DELETE( r );
+}
+
+void DeleteUnsyncedHHState::finishSync( ConduitAction *ca )
+{
+ FUNCTIONSETUP;
+
+ VCalConduitBase *vccb = dynamic_cast<VCalConduitBase*>(ca);
+ if( !vccb )
+ {
+ return;
+ }
+
+ DEBUGKPILOT << fname << ": Finishing DeleteUnsyncedHHState." << endl;
+ vccb->setState( fNextState );
+}
diff --git a/kpilot/conduits/vcalconduit/deleteunsyncedhhstate.h b/kpilot/conduits/vcalconduit/deleteunsyncedhhstate.h
new file mode 100644
index 000000000..df9b721fa
--- /dev/null
+++ b/kpilot/conduits/vcalconduit/deleteunsyncedhhstate.h
@@ -0,0 +1,53 @@
+#ifndef _KPILOT_DUSHHSTATE_H
+#define _KPILOT_DUSHHSTATE_H
+/* deleteunsyncedhhstate.h KPilot
+**
+** Copyright (C) 2006 Bertjan Broeksema
+**
+** This file defines the deleteunsyncedpcstate for vcal-conduitbase.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include "conduitstate.h"
+
+class VCalConduitBase;
+
+/**
+ * State to handle delete unsynced pc records. @see vcal-conduitstate.h
+ */
+class DeleteUnsyncedHHState : public ConduitState
+{
+private:
+ ConduitState *fNextState;
+ int fPilotIndex;
+
+public:
+ DeleteUnsyncedHHState();
+ virtual ~DeleteUnsyncedHHState();
+
+ virtual void startSync( ConduitAction* );
+ virtual void handleRecord( ConduitAction* );
+ virtual void finishSync( ConduitAction* );
+};
+
+#endif
diff --git a/kpilot/conduits/vcalconduit/deleteunsyncedpcstate.cc b/kpilot/conduits/vcalconduit/deleteunsyncedpcstate.cc
new file mode 100644
index 000000000..26a0a0824
--- /dev/null
+++ b/kpilot/conduits/vcalconduit/deleteunsyncedpcstate.cc
@@ -0,0 +1,135 @@
+/* KPilot
+**
+** Copyright (C) 2006 by Bertjan Broeksema <b.broeksema@gmail.com>
+**
+** This file is the implementation of the DeleteUnsyncedPCState.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include <options.h>
+#include <plugin.h>
+
+#include "pilotDatabase.h"
+#include "pilotRecord.h"
+
+#include "vcal-conduitbase.h"
+#include "deleteunsyncedpcstate.h"
+#include "cleanupstate.h"
+
+DeleteUnsyncedPCState::DeleteUnsyncedPCState()
+{
+ fState = eDeleteUnsyncedPC;
+}
+
+DeleteUnsyncedPCState::~DeleteUnsyncedPCState()
+{
+}
+
+void DeleteUnsyncedPCState::startSync( ConduitAction *ca )
+{
+ FUNCTIONSETUP;
+
+ VCalConduitBase *vccb = dynamic_cast<VCalConduitBase*>(ca);
+ if( !vccb )
+ {
+ return;
+ }
+
+ DEBUGKPILOT << fname << ": Starting DeleteUnsyncedPCState." << endl;
+
+ fPilotIndex = 0;
+ fNextState = new CleanUpState();
+
+ vccb->setHasNextRecord( true );
+ fStarted = true;
+}
+
+void DeleteUnsyncedPCState::handleRecord( ConduitAction *ca )
+{
+ FUNCTIONSETUP;
+
+ VCalConduitBase *vccb = dynamic_cast<VCalConduitBase*>(ca);
+ if( !vccb )
+ {
+ return;
+ }
+
+ KCal::Incidence *e = 0L;
+ e = vccb->privateBase()->getNextIncidence();
+
+ // if we don't have a record, then we can't do anything. also, if
+ // we're copying everything from the PC to our handheld, then we're
+ // guaranteed not to have anything extra on our PC that's not on
+ // our handheld that needs to get deleted, so we can return in that
+ // case too...
+
+ if( !e || ( vccb->syncMode().mode() == ConduitAction::SyncMode::eCopyPCToHH ) )
+ {
+ vccb->setHasNextRecord( false );
+ return;
+ }
+
+
+ // try to find the corresponding index on the palm. if we can't
+ // find it, then we have a pc record that needs to be deleted.
+ recordid_t id = e->pilotId();
+
+ PilotRecord *s = 0L;
+
+ if( id > 0 )
+ {
+ s = vccb->database()->readRecordById( id );
+ }
+
+ // if we either have a pc record with no palm id or if we can't
+ // find a palm record that matches, then we need to delete this PC
+ // record.
+ if ( id <=0 || !s )
+ {
+#ifdef DEBUG
+ DEBUGKPILOT << fname << ": found PC entry with pilotID: [" << id
+ << "], Description: [" << e->summary()
+ << "], Time: ["<< e->dtStart().toString() << "] until: ["
+ << e->dtEnd().toString() << "]. Can't find it on Palm, "
+ << "so I'm deleting it from the local calendar." << endl;
+#endif
+ vccb->privateBase()->removeIncidence(e);
+ }
+
+ KPILOT_DELETE( s );
+
+}
+
+void DeleteUnsyncedPCState::finishSync( ConduitAction *ca )
+{
+ FUNCTIONSETUP;
+
+ VCalConduitBase *vccb = dynamic_cast<VCalConduitBase*>(ca);
+ if( !vccb )
+ {
+ return;
+ }
+
+ DEBUGKPILOT << fname << ": Finishing DeleteUnsyncedPCState." << endl;
+ vccb->setState( fNextState );
+}
diff --git a/kpilot/conduits/vcalconduit/deleteunsyncedpcstate.h b/kpilot/conduits/vcalconduit/deleteunsyncedpcstate.h
new file mode 100644
index 000000000..854b2a626
--- /dev/null
+++ b/kpilot/conduits/vcalconduit/deleteunsyncedpcstate.h
@@ -0,0 +1,53 @@
+#ifndef _KPILOT_DUSPCSTATE_H
+#define _KPILOT_DUSPCSTATE_H
+/* deleteunsyncedpcstate.h KPilot
+**
+** Copyright (C) 2006 Bertjan Broeksema
+**
+** This file defines the deleteunsyncedpcstate for vcal-conduitbase.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include "conduitstate.h"
+
+class VCalConduitBase;
+
+/**
+ * State to handle delete unsynced pc records. @see vcal-conduitstate.h
+ */
+class DeleteUnsyncedPCState : public ConduitState
+{
+private:
+ ConduitState *fNextState;
+ int fPilotIndex;
+
+public:
+ DeleteUnsyncedPCState();
+ virtual ~DeleteUnsyncedPCState();
+
+ virtual void startSync( ConduitAction* );
+ virtual void handleRecord( ConduitAction* );
+ virtual void finishSync( ConduitAction* );
+};
+
+#endif
diff --git a/kpilot/conduits/vcalconduit/hhtopcstate.cc b/kpilot/conduits/vcalconduit/hhtopcstate.cc
new file mode 100644
index 000000000..79089671d
--- /dev/null
+++ b/kpilot/conduits/vcalconduit/hhtopcstate.cc
@@ -0,0 +1,249 @@
+/* KPilot
+**
+** Copyright (C) 2006 by Bertjan Broeksema <b.broeksema@gmail.com>
+**
+** This file is the implementation of the HHtoPCState
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include <options.h>
+
+#include "pilotDatabase.h"
+#include "pilotRecord.h"
+
+#include "vcalconduitSettings.h"
+#include "vcal-conduitbase.h"
+#include "hhtopcstate.h"
+#include "pctohhstate.h"
+#include "cleanupstate.h"
+
+HHToPCState::HHToPCState()
+{
+ fState = eHHToPC;
+ fPilotindex = 0;
+}
+
+HHToPCState::~HHToPCState()
+{
+}
+
+void HHToPCState::startSync( ConduitAction *ca )
+{
+ FUNCTIONSETUP;
+
+ VCalConduitBase *vccb = dynamic_cast<VCalConduitBase*>(ca);
+ if( !vccb )
+ {
+ return;
+ }
+
+ DEBUGKPILOT << fname << ": Starting HHToPCState." << endl;
+
+ if ( vccb->syncMode() == ConduitAction::SyncMode::eCopyHHToPC )
+ {
+ fNextState = new CleanUpState();
+ }
+ else
+ {
+ fNextState = new PCToHHState();
+ }
+
+ fStarted = true;
+ vccb->setHasNextRecord( true );
+}
+
+void HHToPCState::handleRecord( ConduitAction *ca )
+{
+ FUNCTIONSETUP;
+
+ VCalConduitBase *vccb = dynamic_cast<VCalConduitBase*>(ca);
+ if( !vccb )
+ {
+ return;
+ }
+
+ PilotRecord *r = 0L;
+ PilotRecord *s = 0L;
+
+ if ( vccb->isFullSync() )
+ {
+ r = vccb->database()->readRecordByIndex( fPilotindex++ );
+ }
+ else
+ {
+ r = vccb->database()->readNextModifiedRec();
+ }
+
+ if (!r)
+ {
+ vccb->privateBase()->updateIncidences();
+ vccb->setHasNextRecord( false );
+ return;
+ }
+
+ // let subclasses do something with the record before we try to sync
+ vccb->preRecord( r );
+
+ bool archiveRecord = ( r->isArchived() );
+ s = vccb->localDatabase()->readRecordById( r->id() );
+
+ if ( !s || vccb->isFirstSync() )
+ {
+#ifdef DEBUG
+ if ( r->id() > 0 && !s )
+ {
+ DEBUGKPILOT << "-------------------------------------------------";
+ DEBUGKPILOT << "--------------------------" << endl;
+ DEBUGKPILOT << fname << ": Could not read palm record with ID ";
+ DEBUGKPILOT << r->id() << endl;
+ }
+#endif
+ if ( !r->isDeleted()
+ || ( vccb->config()->syncArchived() && archiveRecord ) )
+ {
+ KCal::Incidence *e = vccb->addRecord( r );
+ if ( vccb->config()->syncArchived() && archiveRecord ) {
+ e->setSyncStatus( KCal::Incidence::SYNCDEL );
+ }
+ }
+ }
+ else
+ {
+ if ( r->isDeleted() )
+ {
+ if ( vccb->config()->syncArchived() && archiveRecord )
+ {
+ vccb->changeRecord( r, s );
+ }
+ else
+ {
+ vccb->deleteRecord( r, s );
+ }
+ }
+ else
+ {
+ vccb->changeRecord( r, s );
+ }
+ }
+
+ KPILOT_DELETE(r);
+ KPILOT_DELETE(s);
+}
+
+void HHToPCState::finishSync( ConduitAction *ca )
+{
+ FUNCTIONSETUP;
+
+ VCalConduitBase *vccb = dynamic_cast<VCalConduitBase*>(ca);
+ if( !vccb )
+ {
+ return;
+ }
+
+ DEBUGKPILOT << fname << ": Finished HHToPCState." << endl;
+ vccb->setState( fNextState );
+}
+
+/*
+void VCalConduitBase::slotPalmRecToPC()
+{
+ FUNCTIONSETUP;
+
+ PilotRecord *r;
+ if (isFullSync())
+ {
+ r = fDatabase->readRecordByIndex(pilotindex++);
+ }
+ else
+ {
+ r = fDatabase->readNextModifiedRec();
+ }
+ PilotRecord *s = 0L;
+
+ if (!r)
+ {
+ fP->updateIncidences();
+ if ( syncMode()==SyncMode::eCopyHHToPC )
+ {
+ emit logMessage(i18n("Cleaning up ..."));
+ QTimer::singleShot(0, this, SLOT(cleanup()));
+ return;
+ }
+ else
+ {
+ emit logMessage(i18n("Copying records to Pilot ..."));
+ QTimer::singleShot(0 ,this,SLOT(slotPCRecToPalm()));
+ return;
+ }
+ }
+
+ // let subclasses do something with the record before we try to sync
+ preRecord(r);
+
+// DEBUGKPILOT<<fname<<": Event: "<<e->dtStart()<<" until "<<e->dtEnd()<<endl;
+// DEBUGKPILOT<<fname<<": Time: "<<e->dtStart()<<" until "<<e->dtEnd()<<endl;
+ bool archiveRecord=(r->isArchived());
+
+ s = fLocalDatabase->readRecordById(r->id());
+ if (!s || isFirstSync())
+ {
+#ifdef DEBUG
+ if (r->id()>0 && !s)
+ {
+ DEBUGKPILOT<<"---------------------------------------------------------------------------"<<endl;
+ DEBUGKPILOT<< fname<<": Could not read palm record with ID "<<r->id()<<endl;
+ }
+#endif
+ if (!r->isDeleted() || (config()->syncArchived() && archiveRecord))
+ {
+ KCal::Incidence*e=addRecord(r);
+ if (config()->syncArchived() && archiveRecord) {
+ e->setSyncStatus(KCal::Incidence::SYNCDEL);
+ }
+ }
+ }
+ else
+ {
+ if (r->isDeleted())
+ {
+ if (config()->syncArchived() && archiveRecord)
+ {
+ changeRecord(r,s);
+ }
+ else
+ {
+ deleteRecord(r,s);
+ }
+ }
+ else
+ {
+ changeRecord(r,s);
+ }
+ }
+
+ KPILOT_DELETE(r);
+ KPILOT_DELETE(s);
+
+ QTimer::singleShot(0,this,SLOT(slotPalmRecToPC()));
+}
+*/
diff --git a/kpilot/conduits/vcalconduit/hhtopcstate.h b/kpilot/conduits/vcalconduit/hhtopcstate.h
new file mode 100644
index 000000000..838828e61
--- /dev/null
+++ b/kpilot/conduits/vcalconduit/hhtopcstate.h
@@ -0,0 +1,55 @@
+#ifndef _KPILOT_HHTOPCSTATE_H
+#define _KPILOT_HHTOPCSTATE_H
+/* hhtopcstate.h KPilot
+**
+** Copyright (C) 2006 Bertjan Broeksema
+**
+** This file defines the teststate for vcal-conduitbase.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include <libkcal/calendarlocal.h>
+
+#include "conduitstate.h"
+
+class VCalConduitBase;
+
+/**
+ * State to test the vcal-conduit. @see vcal-conduitstate.h
+ */
+class HHToPCState : public ConduitState
+{
+private:
+ ConduitState *fNextState;
+ int fPilotindex;
+
+public:
+ HHToPCState();
+ virtual ~HHToPCState();
+
+ virtual void startSync( ConduitAction* );
+ virtual void handleRecord( ConduitAction* );
+ virtual void finishSync( ConduitAction* );
+};
+
+#endif
diff --git a/kpilot/conduits/vcalconduit/initstate.cc b/kpilot/conduits/vcalconduit/initstate.cc
new file mode 100644
index 000000000..23257ff35
--- /dev/null
+++ b/kpilot/conduits/vcalconduit/initstate.cc
@@ -0,0 +1,109 @@
+/* KPilot
+**
+** Copyright (C) 2006 by Bertjan Broeksema <b.broeksema@gmail.com>
+**
+** This file is the implementation of the InitState.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include <options.h>
+#include <plugin.h>
+
+#include "vcal-conduitbase.h"
+#include "initstate.h"
+#include "teststate.h"
+#include "pctohhstate.h"
+#include "hhtopcstate.h"
+
+InitState::InitState()
+{
+ fState = eInit;
+}
+
+InitState::~InitState()
+{
+}
+
+void InitState::startSync( ConduitAction *ca )
+{
+ FUNCTIONSETUP;
+
+ VCalConduitBase *vccb = dynamic_cast<VCalConduitBase*>(ca);
+ if( !vccb )
+ {
+ return;
+ }
+
+ DEBUGKPILOT << fname << ": Starting InitState." << endl;
+
+ vccb->addLogMessage( i18n( "Initializing conduit ..." ) );
+ vccb->preSync();
+
+ if ( vccb->syncMode().isTest() )
+ {
+ fNextState = new TestState();
+ }
+ else
+ {
+ switch( vccb->syncMode().mode() )
+ {
+ case ConduitAction::SyncMode::eCopyPCToHH:
+ // TODO: Clear the palm and backup database??? Or just add the
+ // new items ignore the Palm->PC side and leave the existing items
+ // on the palm?
+ fNextState = new PCToHHState();
+ break;
+ case ConduitAction::SyncMode::eCopyHHToPC:
+ // TODO: Clear the backup database and the calendar, update fP
+ // or just add the palm items and leave the PC ones there????
+ fNextState = new HHToPCState();
+ break;
+ default:
+ fNextState = new HHToPCState();
+ break;
+ }
+ }
+
+ fStarted = true;
+ vccb->setHasNextRecord( false );
+}
+
+void InitState::handleRecord( ConduitAction *vccb )
+{
+ FUNCTIONSETUP;
+ Q_UNUSED(vccb);
+}
+
+void InitState::finishSync( ConduitAction *ca )
+{
+ FUNCTIONSETUP;
+
+ VCalConduitBase *vccb = dynamic_cast<VCalConduitBase*>(ca);
+ if( !vccb )
+ {
+ return;
+ }
+
+ DEBUGKPILOT << fname << ": Finished InitState." << endl;
+ vccb->setState( fNextState );
+}
diff --git a/kpilot/conduits/vcalconduit/initstate.h b/kpilot/conduits/vcalconduit/initstate.h
new file mode 100644
index 000000000..83042ba2a
--- /dev/null
+++ b/kpilot/conduits/vcalconduit/initstate.h
@@ -0,0 +1,52 @@
+#ifndef _KPILOT_INITSTATE_H
+#define _KPILOT_INITSTATE_H
+/* initstate.h KPilot
+**
+** Copyright (C) 2006 Bertjan Broeksema
+**
+** This file defines the teststate for vcal-conduitbase.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include "conduitstate.h"
+
+class VCalConduitBase;
+
+/**
+ * State to test the vcal-conduit. @see vcal-conduitstate.h
+ */
+class InitState : public ConduitState
+{
+private:
+ ConduitState *fNextState;
+
+public:
+ InitState();
+ virtual ~InitState();
+
+ virtual void startSync( ConduitAction *vccb );
+ virtual void handleRecord( ConduitAction *vccb );
+ virtual void finishSync( ConduitAction *vccb );
+};
+
+#endif
diff --git a/kpilot/conduits/vcalconduit/kcalRecord.cc b/kpilot/conduits/vcalconduit/kcalRecord.cc
new file mode 100644
index 000000000..f12d9b8c3
--- /dev/null
+++ b/kpilot/conduits/vcalconduit/kcalRecord.cc
@@ -0,0 +1,143 @@
+/* kcalRecord.cc KPilot
+**
+** Copyright (C) 2006 by Adriaan de Groot <groot@kde.org>
+** Copyright (C) 2002-2003 by Reinhold Kainhofer
+** Copyright (C) 2001 by Dan Pilone
+**
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include "options.h"
+
+#include <libkcal/calendar.h>
+#include <libkcal/calendarlocal.h>
+#include <libkcal/recurrence.h>
+#include <libkcal/vcalformat.h>
+
+#include "pilot.h"
+#include "pilotRecord.h"
+#include "kcalRecord.h"
+
+void KCalSync::setCategory(PilotRecordBase *de,
+ const KCal::Incidence *e,
+ const CategoryAppInfo &info)
+{
+ FUNCTIONSETUP;
+
+ if (!de || !e)
+ {
+ return;
+ }
+
+ QString deCategory;
+ QStringList eventCategories = e->categories();
+ if (eventCategories.size() < 1)
+ {
+ // This event has no categories.
+ de->setCategory(Pilot::Unfiled);
+ return;
+ }
+
+ // Quick check: does the record (not unfiled) have an entry
+ // in the categories list? If so, use that.
+ if (de->category() != Pilot::Unfiled)
+ {
+ deCategory = Pilot::categoryName(&info,de->category());
+ if (eventCategories.contains(deCategory))
+ {
+ // Found, so leave the category unchanged.
+ return;
+ }
+ }
+
+ QStringList availableHandheldCategories = Pilot::categoryNames(&info);
+
+ // Either the record is unfiled, and should be filed, or
+ // it has a category set which is not in the list of
+ // categories that the event has. So go looking for
+ // a category that is available both for the event
+ // and on the handheld.
+ for ( QStringList::ConstIterator it = eventCategories.begin();
+ it != eventCategories.end(); ++it )
+ {
+ // Odd, an empty category string.
+ if ( (*it).isEmpty() )
+ {
+ continue;
+ }
+
+ if (availableHandheldCategories.contains(*it))
+ {
+ // Since the string is in the list of available categories,
+ // this *can't* fail.
+ int c = Pilot::findCategory(&info,*it,false);
+ Q_ASSERT( Pilot::validCategory(c) );
+ de->setCategory(c);
+ return;
+ }
+ }
+
+ de->setCategory(Pilot::Unfiled);
+}
+
+void KCalSync::setCategory(KCal::Incidence *e,
+ const PilotRecordBase *de,
+ const CategoryAppInfo &info)
+{
+ FUNCTIONSETUP;
+
+ if (!e || !de)
+ {
+ DEBUGKPILOT << fname << ": error. unable to set kcal category. e: ["
+ << (void *)e << "], de: [" << (void *)de << "]" << endl;
+ return;
+ }
+
+ QStringList cats=e->categories();
+ int cat = de->category();
+ QString newcat = Pilot::categoryName(&info,cat);
+
+ DEBUGKPILOT << fname << ": palm category id: [" << cat <<
+ "], label: [" << newcat << "]" << endl;
+
+ if ( Pilot::validCategory(cat) && (cat != Pilot::Unfiled))
+ {
+ if (!cats.contains(newcat))
+ {
+ // if this event only has one category associated with it, then we can
+ // safely assume that what we should be doing here is changing it to match
+ // the palm. if there's already more than one category in the event, however, we
+ // won't cause data loss--we'll just append what the palm has to the
+ // event's categories
+ if (cats.count() <=1)
+ {
+ cats.clear();
+ }
+
+ cats.append( newcat );
+ e->setCategories(cats);
+ }
+ }
+
+ DEBUGKPILOT << fname << ": kcal categories now: [" << cats.join(",") << "]" << endl;
+}
diff --git a/kpilot/conduits/vcalconduit/kcalRecord.h b/kpilot/conduits/vcalconduit/kcalRecord.h
new file mode 100644
index 000000000..efd916e81
--- /dev/null
+++ b/kpilot/conduits/vcalconduit/kcalRecord.h
@@ -0,0 +1,49 @@
+#ifndef _KPILOT_KCALRECORD_H
+#define _KPILOT_KCALRECORD_H
+/*
+** Copyright (C) 2006 by Adriaan de Groot <groot@kde.org>
+** Copyright (C) 2002-2003 by Reinhold Kainhofer
+** Copyright (C) 2001 by Dan Pilone
+**
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+class PilotRecordBase;
+
+namespace KCal
+{
+ class Incidence;
+}
+
+namespace KCalSync
+{
+ void setCategory(PilotRecordBase *de,
+ const KCal::Incidence *incidence,
+ const CategoryAppInfo &info);
+ void setCategory(KCal::Incidence *e,
+ const PilotRecordBase *de,
+ const CategoryAppInfo &info);
+}
+
+#endif
+
diff --git a/kpilot/conduits/vcalconduit/korganizerConduit.ui b/kpilot/conduits/vcalconduit/korganizerConduit.ui
new file mode 100644
index 000000000..1a9d6557b
--- /dev/null
+++ b/kpilot/conduits/vcalconduit/korganizerConduit.ui
@@ -0,0 +1,275 @@
+<!DOCTYPE UI><UI version="3.1" stdsetdef="1">
+<class>VCalWidget</class>
+<author>Adriaan de Groot</author>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>Form1</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>593</width>
+ <height>209</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="baseSize">
+ <size>
+ <width>570</width>
+ <height>270</height>
+ </size>
+ </property>
+ <property name="caption">
+ <string>Calendar-Conduit Options</string>
+ </property>
+ <property name="layoutMargin" stdset="0">
+ </property>
+ <property name="layoutSpacing" stdset="0">
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QTabWidget" row="0" column="0">
+ <property name="name">
+ <cstring>tabWidget</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="layoutMargin" stdset="0">
+ </property>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>Widget2</cstring>
+ </property>
+ <attribute name="title">
+ <string>General</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer row="2" column="0">
+ <property name="name">
+ <cstring>Spacer4</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>
+ <widget class="QButtonGroup" row="0" column="0">
+ <property name="name">
+ <cstring>fSyncDestination</cstring>
+ </property>
+ <property name="title">
+ <string>Sync Destination</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QRadioButton" row="0" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>fSyncStdCalendar</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Standard calendar</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Select this option to synchronize with the calendar specified by the KDE calendar settings.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="1" column="0">
+ <property name="name">
+ <cstring>fSyncFile</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Calendar &amp;file:</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Select this option to use a specific calendar file, instead of the standard KDE calendar. This file must be in the in the vCalendar or iCalendar format. Enter the location of this file in the edit box or select it clicking the file picker button.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="KURLRequester" row="1" column="1">
+ <property name="name">
+ <cstring>fCalendarFile</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Enter here the location and filename of the calendar file or select it clicking the file picker button. This file must be in the iCalendar or vCalendar format.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QCheckBox" row="1" column="0">
+ <property name="name">
+ <cstring>fArchive</cstring>
+ </property>
+ <property name="text">
+ <string>Store &amp;archived records in the KDE calendar</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>When this box is checked, archived records will still
+be saved in the calendar on the PC.</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Conflicts</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>fTextLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>4</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Conflict &amp;resolution:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>fConflictResolution</cstring>
+ </property>
+ </widget>
+ <widget class="QComboBox" row="0" column="1">
+ <item>
+ <property name="text">
+ <string>Use KPilot's Global Setting</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Ask User</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Do Nothing</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Handheld Overrides</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>PC Overrides</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Values From Last Sync (if possible)</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Use Both Entries</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>fConflictResolution</cstring>
+ </property>
+ <property name="currentItem">
+ <number>6</number>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Select in this list how conflicting entries (entries which were edited both on your handheld and on the PC) are resolved. Possibly values are "Use KPilot's Global Setting" to use the settings defined in KPilot HotSync configuration, "Ask User" to let you decide case by case, "Do Nothing" to allow the entries to be different, "PC overrides", "Handheld overrides", "Use values from last sync" and "Use both entries" to create a new entry on both the PC and handheld. Note that this does &lt;i&gt;not&lt;/i&gt; handle double-scheduling conflicts.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <spacer row="1" column="1">
+ <property name="name">
+ <cstring>spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>31</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+ </widget>
+ </widget>
+ </grid>
+</widget>
+<connections>
+ <connection>
+ <sender>fSyncFile</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>fCalendarFile</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+</connections>
+<tabstops>
+ <tabstop>tabWidget</tabstop>
+</tabstops>
+<layoutdefaults spacing="6" margin="11"/>
+<includes>
+ <include location="global" impldecl="in implementation">kurlrequester.h</include>
+ <include location="global" impldecl="in implementation">klineedit.h</include>
+ <include location="global" impldecl="in implementation">kpushbutton.h</include>
+</includes>
+</UI>
diff --git a/kpilot/conduits/vcalconduit/pctohhstate.cc b/kpilot/conduits/vcalconduit/pctohhstate.cc
new file mode 100644
index 000000000..b68771f13
--- /dev/null
+++ b/kpilot/conduits/vcalconduit/pctohhstate.cc
@@ -0,0 +1,159 @@
+/* KPilot
+**
+** Copyright (C) 2006 by Bertjan Broeksema <b.broeksema@gmail.com>
+**
+** This file is the implementation of the PCToHHState.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include <options.h>
+
+#include "pilotDatabase.h"
+#include "pilotRecord.h"
+
+#include "vcal-conduitbase.h"
+#include "pctohhstate.h"
+#include "cleanupstate.h"
+#include "deleteunsyncedhhstate.h"
+
+PCToHHState::PCToHHState()
+{
+ fState = ePCToHH;
+}
+
+PCToHHState::~PCToHHState()
+{
+}
+
+void PCToHHState::startSync( ConduitAction *ca )
+{
+ FUNCTIONSETUP;
+ VCalConduitBase *vccb = dynamic_cast<VCalConduitBase*>(ca);
+ if( !vccb )
+ {
+ return;
+ }
+
+ DEBUGKPILOT << fname << ": Starting PCToHHState." << endl;
+
+ // if we are asked to copy HH to PC, we shouldn't look for deleted records
+ // on the Palm, since we've just copied them all. =:) Otherwise, look for
+ // data on the palm that shouldn't be there and delete it if we find it....
+ if ( vccb->syncMode() == ConduitAction::SyncMode::eCopyHHToPC )
+ {
+ fNextState = new CleanUpState();
+ }
+ else
+ {
+ fNextState = new DeleteUnsyncedHHState();
+ }
+
+ vccb->addLogMessage( i18n( "Copying records to Pilot ..." ) );
+
+ fStarted = true;
+ vccb->setHasNextRecord( true );
+}
+
+void PCToHHState::handleRecord( ConduitAction *ca )
+{
+ FUNCTIONSETUP;
+ VCalConduitBase *vccb = dynamic_cast<VCalConduitBase*>(ca);
+ if( !vccb )
+ {
+ return;
+ }
+
+ KCal::Incidence *e = 0L;
+
+ if( vccb->isFullSync() )
+ {
+ e = vccb->privateBase()->getNextIncidence();
+ }
+ else
+ {
+ e = vccb->privateBase()->getNextModifiedIncidence();
+ }
+
+ // No more incidences to sync
+ if( !e )
+ {
+ vccb->setHasNextRecord( false );
+ return;
+ }
+
+ // let subclasses do something with the event
+ vccb->preIncidence( e );
+
+ // find the corresponding index on the palm and sync. If there is none,
+ // create it.
+ recordid_t id = e->pilotId();
+
+ DEBUGKPILOT << fname << ": found PC entry with pilotID " << id <<endl;
+ DEBUGKPILOT << fname << ": Description: " << e->summary() << endl;
+
+ QDateTime start_time = e->dtStart();
+ QDateTime end_time = e->dtEnd();
+ DEBUGKPILOT << fname << ": Time: "<< start_time.toString() << " until "
+ << end_time.toString() << endl;
+
+ PilotRecord *s = 0L;
+
+ if( id > 0 && ( s = vccb->database()->readRecordById( id ) ) )
+ {
+ if( e->syncStatus() == KCal::Incidence::SYNCDEL )
+ {
+ vccb->deletePalmRecord( e, s );
+ }
+ else
+ {
+ vccb->changePalmRecord( e, s );
+ }
+
+ KPILOT_DELETE( s );
+ } else {
+#ifdef DEBUG
+ if (id > 0 )
+ {
+ DEBUGKPILOT << "-------------------------------------------------"
+ << "--------------------------" << endl;
+ DEBUGKPILOT << fname << ": Could not read palm record with ID "
+ << id << endl;
+ }
+#endif
+ vccb->addPalmRecord( e );
+ }
+}
+
+void PCToHHState::finishSync( ConduitAction *ca )
+{
+ FUNCTIONSETUP;
+
+ VCalConduitBase *vccb = dynamic_cast<VCalConduitBase*>(ca);
+ if( !vccb )
+ {
+ return;
+ }
+
+ DEBUGKPILOT << fname << ": Finished PCToHHState." << endl;
+ vccb->setState( fNextState );
+}
diff --git a/kpilot/conduits/vcalconduit/pctohhstate.h b/kpilot/conduits/vcalconduit/pctohhstate.h
new file mode 100644
index 000000000..44f929d68
--- /dev/null
+++ b/kpilot/conduits/vcalconduit/pctohhstate.h
@@ -0,0 +1,54 @@
+#ifndef _KPILOT_PCTOHHSTATE_H
+#define _KPILOT_PCTOHHSTATE_H
+/* pctohhstate.h KPilot
+**
+** Copyright (C) 2006 Bertjan Broeksema
+**
+** This file defines the pctohhstate for vcal-conduitbase.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include "conduitstate.h"
+
+class VCalConduitBase;
+
+/**
+ * State that handles copying of records from pc to handheld.
+ * @see vcal-conduitstate.h
+ */
+class PCToHHState : public ConduitState
+{
+private:
+ ConduitState *fNextState;
+ int fPilotindex;
+
+public:
+ PCToHHState();
+ virtual ~PCToHHState();
+
+ virtual void startSync( ConduitAction* );
+ virtual void handleRecord( ConduitAction* );
+ virtual void finishSync( ConduitAction* );
+};
+
+#endif
diff --git a/kpilot/conduits/vcalconduit/teststate.cc b/kpilot/conduits/vcalconduit/teststate.cc
new file mode 100644
index 000000000..d8c8e56cc
--- /dev/null
+++ b/kpilot/conduits/vcalconduit/teststate.cc
@@ -0,0 +1,127 @@
+/* KPilot
+**
+** Copyright (C) 2006 by Bertjan Broeksema <b.broeksema@gmail.com>
+**
+** This file is the implementation of the TestState.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include <options.h>
+
+#include <qdatetime.h>
+#include <qfile.h>
+
+#include "pilotSerialDatabase.h"
+#include "pilotLocalDatabase.h"
+#include "pilotDateEntry.h"
+
+#include "teststate.h"
+#include "vcal-conduitbase.h"
+
+TestState::TestState() : fCalendar( QString::null )
+{
+ fState = eTest;
+}
+
+TestState::~TestState()
+{
+ FUNCTIONSETUP;
+}
+
+void TestState::startSync( ConduitAction *ca )
+{
+ FUNCTIONSETUP;
+
+ VCalConduitBase *vccb = dynamic_cast<VCalConduitBase*>(ca);
+ if( !vccb )
+ {
+ return;
+ }
+
+ DEBUGKPILOT << fname << ": Starting teststate." << endl;
+
+ vccb->setHasNextRecord( true );
+ fPilotindex = 0;
+ fStarted = true;
+}
+
+void TestState::handleRecord( ConduitAction *ca )
+{
+ FUNCTIONSETUP;
+
+ VCalConduitBase *vccb = dynamic_cast<VCalConduitBase*>(ca);
+ if( !vccb )
+ {
+ return;
+ }
+
+ DEBUGKPILOT << fname << ": Handling record " << fPilotindex << endl;
+
+ PilotRecord *record = vccb->readRecordByIndex( fPilotindex );
+
+ if( record )
+ {
+ KCal::Incidence *i = vccb->incidenceFromRecord( record );
+ fCalendar.addIncidence( i );
+
+ KPILOT_DELETE(record);
+
+ // Schedule more work.
+ ++fPilotindex;
+ }
+ else
+ {
+ vccb->setHasNextRecord( false );
+ }
+}
+
+void TestState::finishSync( ConduitAction *ca )
+{
+ FUNCTIONSETUP;
+
+ VCalConduitBase *vccb = dynamic_cast<VCalConduitBase*>(ca);
+ if( !vccb )
+ {
+ return;
+ }
+
+ DEBUGKPILOT << fname << ": finishing teststate." << endl;
+
+ // No more records present on the device so lets dump the
+ // readed records in a file.
+ QFile f( CSL1("dump.ics") );
+ if( !f.exists() )
+ {
+ f.open( IO_WriteOnly );
+ f.close();
+ }
+
+ if( !fCalendar.save( CSL1("dump.ics") ) )
+ {
+ DEBUGKPILOT << fname << ": Can't save calendar file." << endl;
+ }
+
+ fCalendar.close();
+
+ vccb->setState( 0L );
+}
diff --git a/kpilot/conduits/vcalconduit/teststate.h b/kpilot/conduits/vcalconduit/teststate.h
new file mode 100644
index 000000000..76361e36a
--- /dev/null
+++ b/kpilot/conduits/vcalconduit/teststate.h
@@ -0,0 +1,55 @@
+#ifndef _KPILOT_TESTSTATE_H
+#define _KPILOT_TESTSTATE_H
+/* teststate.h KPilot
+**
+** Copyright (C) 2006 Bertjan Broeksema
+**
+** This file defines the teststate for vcal-conduitbase.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include <libkcal/calendarlocal.h>
+
+#include "conduitstate.h"
+
+class VCalConduitBase;
+
+/**
+ * State to test the vcal-conduit. @see vcal-conduitstate.h
+ */
+class TestState : public ConduitState
+{
+private:
+ KCal::CalendarLocal fCalendar;
+ int fPilotindex;
+
+public:
+ TestState();
+ virtual ~TestState();
+
+ virtual void startSync( ConduitAction* );
+ virtual void handleRecord( ConduitAction* );
+ virtual void finishSync( ConduitAction* );
+};
+
+#endif
diff --git a/kpilot/conduits/vcalconduit/todo-conduit.cc b/kpilot/conduits/vcalconduit/todo-conduit.cc
new file mode 100644
index 000000000..302ada565
--- /dev/null
+++ b/kpilot/conduits/vcalconduit/todo-conduit.cc
@@ -0,0 +1,373 @@
+/* Todo-Conduit for syncing KPilot and KOrganizer
+**
+** Copyright (C) 2002-2003 Reinhold Kainhofer
+** Copyright (C) 1998-2001 Dan Pilone
+** Copyright (C) 1998-2000 Preston Brown <pbrown@kde.org>
+** Copyright (C) 1998 Herwin-Jan Steehouwer
+** Copyright (C) 2001 Cornelius Schumacher
+**
+** This file is part of the todo conduit, a conduit for KPilot that
+** synchronises the Pilot's todo application with the outside world,
+** which currently means KOrganizer.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include "options.h"
+
+#include <qdatetime.h>
+#include <qtextcodec.h>
+
+#include <libkcal/calendar.h>
+#include <libkcal/todo.h>
+
+#include <pilotLocalDatabase.h>
+
+#include "todo-conduit.moc"
+#include "vcalconduitSettings.h"
+#include "todo-factory.h"
+
+#include "kcalRecord.h"
+#include "todoRecord.h"
+
+// define conduit versions, one for the version when categories were synced for the first time, and the current version number
+#define CONDUIT_VERSION_CATEGORYSYNC 10
+#define CONDUIT_VERSION 10
+
+extern "C"
+{
+unsigned long version_conduit_todo = Pilot::PLUGIN_API;
+}
+
+
+TodoConduitPrivate::TodoConduitPrivate(KCal::Calendar *b) :
+ VCalConduitPrivateBase(b)
+{
+ fAllTodos.setAutoDelete(false);
+}
+
+void TodoConduitPrivate::addIncidence(KCal::Incidence*e)
+{
+ fAllTodos.append(static_cast<KCal::Todo*>(e));
+ fCalendar->addTodo(static_cast<KCal::Todo*>(e));
+}
+
+int TodoConduitPrivate::updateIncidences()
+{
+ fAllTodos = fCalendar->todos();
+ fAllTodos.setAutoDelete(false);
+ return fAllTodos.count();
+}
+
+
+void TodoConduitPrivate::removeIncidence(KCal::Incidence *e)
+{
+ fAllTodos.remove(static_cast<KCal::Todo*>(e));
+ if (!fCalendar) return;
+ fCalendar->deleteTodo(static_cast<KCal::Todo*>(e));
+ // now just in case we're in the middle of reading through our list
+ // and we delete something, set reading to false so we start at the
+ // top again next time and don't have problems with our iterator
+ reading = false;
+}
+
+
+
+KCal::Incidence *TodoConduitPrivate::findIncidence(recordid_t id)
+{
+ KCal::Todo::List::ConstIterator it;
+ for( it = fAllTodos.begin(); it != fAllTodos.end(); ++it ) {
+ KCal::Todo *todo = *it;
+ if ((recordid_t)(todo->pilotId()) == id) return todo;
+ }
+
+ return 0L;
+}
+
+
+
+KCal::Incidence *TodoConduitPrivate::findIncidence(PilotRecordBase *tosearch)
+{
+ PilotTodoEntry*entry=dynamic_cast<PilotTodoEntry*>(tosearch);
+ if (!entry) return 0L;
+
+ QString title=entry->getDescription();
+ QDateTime dt=readTm( entry->getDueDate() );
+
+ KCal::Todo::List::ConstIterator it;
+ for( it = fAllTodos.begin(); it != fAllTodos.end(); ++it ) {
+ KCal::Todo *event = *it;
+ if ( (event->dtDue().date() == dt.date()) && (event->summary() == title) ) return event;
+ }
+ return 0L;
+}
+
+
+
+KCal::Incidence *TodoConduitPrivate::getNextIncidence()
+{
+ FUNCTIONSETUP;
+ if (reading) {
+ ++fAllTodosIterator;
+ }
+ else {
+ reading=true;
+ fAllTodosIterator = fAllTodos.begin();
+ }
+
+ return(fAllTodosIterator == fAllTodos.end()) ? 0L : *fAllTodosIterator;
+}
+
+
+
+KCal::Incidence *TodoConduitPrivate::getNextModifiedIncidence()
+{
+ FUNCTIONSETUP;
+ KCal::Todo*e=0L;
+ if (!reading)
+ {
+ reading=true;
+ fAllTodosIterator = fAllTodos.begin();
+ }
+ else
+ {
+ ++fAllTodosIterator;
+ }
+ if ( fAllTodosIterator != fAllTodos.end() ) e=*fAllTodosIterator;
+ while (fAllTodosIterator != fAllTodos.end() &&
+ e && e->syncStatus()!=KCal::Incidence::SYNCMOD && e->pilotId())
+ {
+ e = (++fAllTodosIterator != fAllTodos.end()) ? *fAllTodosIterator : 0L;
+
+#ifdef DEBUG
+ if(e)
+ DEBUGKPILOT<< e->summary()<<" had SyncStatus="<<e->syncStatus()<<endl;
+#endif
+
+ }
+
+ return (fAllTodosIterator == fAllTodos.end()) ? 0L : *fAllTodosIterator;
+}
+
+
+
+/****************************************************************************
+ * TodoConduit class *
+ ****************************************************************************/
+
+TodoConduit::TodoConduit(KPilotLink *d,
+ const char *n,
+ const QStringList &a) : VCalConduitBase(d,n,a),
+ fTodoAppInfo( 0L )
+{
+ FUNCTIONSETUP;
+ fConduitName=i18n("To-do");
+}
+
+
+
+TodoConduit::~TodoConduit()
+{
+// FUNCTIONSETUP;
+}
+
+
+
+void TodoConduit::_setAppInfo()
+{
+ FUNCTIONSETUP;
+ // get the address application header information
+
+ if( !fTodoAppInfo )
+ {
+ DEBUGKPILOT << fname << ": fTodoAppInfo is NULL" << endl;
+ return;
+ }
+ if( !fDatabase )
+ {
+ DEBUGKPILOT << fname << ": fDatabase is NULL" << endl;
+ return;
+ }
+
+ fTodoAppInfo->writeTo(fDatabase);
+}
+
+void TodoConduit::_getAppInfo()
+{
+ FUNCTIONSETUP;
+ // get the address application header information
+
+ KPILOT_DELETE( fTodoAppInfo );
+ fTodoAppInfo = new PilotToDoInfo(fDatabase);
+ fTodoAppInfo->dump();
+}
+
+
+
+const QString TodoConduit::getTitle(PilotRecordBase *de)
+{
+ PilotTodoEntry*d=dynamic_cast<PilotTodoEntry*>(de);
+ if (d)
+ {
+ return QString(d->getDescription());
+ }
+ return QString::null;
+}
+
+
+
+void TodoConduit::readConfig()
+{
+ FUNCTIONSETUP;
+ VCalConduitBase::readConfig();
+ // determine if the categories have ever been synce. Needed to prevent loosing
+ // the categories on the desktop. Also use a full sync for the first time to
+ // make sure the palm categories are really transferred to the desktop.
+ //
+ categoriesSynced = config()->conduitVersion()>=CONDUIT_VERSION_CATEGORYSYNC;
+ if (!categoriesSynced && !isFullSync() )
+ {
+ changeSync(SyncMode::eFullSync);
+ }
+ DEBUGKPILOT<<"categoriesSynced=" << categoriesSynced << endl;
+}
+
+void TodoConduit::preSync()
+{
+ FUNCTIONSETUP;
+ VCalConduitBase::preSync();
+ _getAppInfo();
+}
+
+void TodoConduit::postSync()
+{
+ FUNCTIONSETUP;
+ VCalConduitBase::postSync();
+ // after this successful sync the categories have been synced for sure
+ config()->setConduitVersion( CONDUIT_VERSION );
+ config()->writeConfig();
+ _setAppInfo();
+}
+
+
+
+PilotRecord *TodoConduit::recordFromIncidence(PilotRecordBase *de, const KCal::Incidence *e)
+{
+ FUNCTIONSETUP;
+
+ if (!de || !e)
+ {
+ DEBUGKPILOT << fname
+ << ": got NULL entry or NULL incidence." << endl;
+ return 0L;
+ }
+
+ PilotTodoEntry *todoEntry = dynamic_cast<PilotTodoEntry*>(de);
+ if (!todoEntry)
+ {
+ // Secretly wasn't a todo entry after all
+ return 0L;
+ }
+
+ const KCal::Todo *todo = dynamic_cast<const KCal::Todo *>(e);
+ if (!todo)
+ {
+ DEBUGKPILOT << fname << ": Incidence is not a todo." << endl;
+ return 0L;
+ }
+
+ // don't need to check for null pointers here, the recordFromIncidence(PTE*, KCal::Todo*) will do that.
+ if (KCalSync::setTodoEntry(todoEntry,todo,*fTodoAppInfo->categoryInfo()))
+ {
+ return todoEntry->pack();
+ }
+ else
+ {
+ return 0L;
+ }
+}
+
+KCal::Incidence *TodoConduit::incidenceFromRecord(KCal::Incidence *e, const PilotRecordBase *de)
+{
+ FUNCTIONSETUP;
+
+ if (!de || !e)
+ {
+ DEBUGKPILOT << fname
+ << ": Got NULL entry or NULL incidence." << endl;
+ return 0L;
+ }
+
+ const PilotTodoEntry *todoEntry = dynamic_cast<const PilotTodoEntry *>(de);
+ if (!todoEntry)
+ {
+ DEBUGKPILOT << fname << ": HH record not a todo entry." << endl;
+ return 0L;
+ }
+
+ KCal::Todo *todo = dynamic_cast<KCal::Todo *>(e);
+ if (!todo)
+ {
+ DEBUGKPILOT << fname << ": Incidence is not a todo." << endl;
+ return 0L;
+ }
+
+ KCalSync::setTodo(todo, todoEntry,*fTodoAppInfo->categoryInfo());
+ return e;
+}
+
+
+
+
+
+void TodoConduit::preRecord(PilotRecord*r)
+{
+ FUNCTIONSETUP;
+ if (!categoriesSynced && r)
+ {
+ const PilotRecordBase *de = newPilotEntry(r);
+ KCal::Incidence *e = fP->findIncidence(r->id());
+ KCalSync::setCategory(dynamic_cast<KCal::Todo*>(e),
+ dynamic_cast<const PilotTodoEntry*>(de),
+ *fTodoAppInfo->categoryInfo());
+ }
+}
+
+
+
+
+
+
+static VCalConduitSettings *config_vcal = 0L;
+
+VCalConduitSettings *TodoConduit::theConfig() {
+ if (!config_vcal)
+ {
+ config_vcal = new VCalConduitSettings(CSL1("Calendar"));
+ }
+
+ return config_vcal;
+}
+
+VCalConduitSettings *TodoConduit::config() {
+ return theConfig();
+}
diff --git a/kpilot/conduits/vcalconduit/todo-conduit.desktop b/kpilot/conduits/vcalconduit/todo-conduit.desktop
new file mode 100644
index 000000000..dcf7c2225
--- /dev/null
+++ b/kpilot/conduits/vcalconduit/todo-conduit.desktop
@@ -0,0 +1,107 @@
+[Desktop Entry]
+Type=Service
+Comment=This conduit syncs the ToDo list from your handheld to KOrganizer.
+Comment[af]=Hierdie pad sinkroniseer die Te-doen lys vanaf jou draagbare toestel na KOrganizer.
+Comment[bg]=Ð¡Ð¸Ð½Ñ…Ñ€Ð¾Ð½Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð½Ð° ÑпиÑъка ÑÑŠÑ Ð·Ð°Ð´Ð°Ñ‡Ð¸ на мобилно уÑтройÑтво Ñ Ð¾Ñ€Ð³Ð°Ð½Ð¸Ð·Ð°Ñ‚Ð¾Ñ€Ð° в KDE
+Comment[bs]=Ovaj conduit sinhronizuje listu Zadataka na ruÄnom raÄunaru sa KOrganizerom.
+Comment[ca]=Aquest conducte sincronitza la llista de pendents des de la vostra agenda electrònica a KOrganizer.
+Comment[cs]=Toto propojení synchronizuje seznam úkolů s KOrganizérem
+Comment[cy]=Mae'r cwndid yma yn cydamseru'r rhestr I-Wneud o'ch llawiadur i KTrefnydd.
+Comment[da]=Denne kanal synkroniserer din gøremålsliste fra din håndholdte til KOrganizer.
+Comment[de]=Abgleich der Aufgabenlisten von Taschencomputer und KOrganizer
+Comment[el]=Αυτός ο σÏνδεσμος συγχÏονίζει τη λίστα Ï€Ïος υλοποίηση από τον υπολογιστή παλάμης σας στο KOrganizer.
+Comment[eo]=Tiu kanalo sinkronigas la farendaĵliston de via poÅkomputilo kun KOrganizilo.
+Comment[es]=Este conducto sincroniza la lista de tareas pendientes de su agenda electrónica con KOrganizer.
+Comment[et]=See kanal sünkroniseerib pihuarvuti ja KOrganizeri ülesannete nimekirja.
+Comment[eu]=Kanal honek zure agenda elektronikoko egitekoen zerrenda KOrganizer-era sinkronizatzen du.
+Comment[fa]=این لوله، Ùهرست کارهایی Ú©Ù‡ باید انجام شود را از دستی شما با KOrganizer همگام‌سازی می‌کند.
+Comment[fi]=Tämä yhdyskäytävä synkronoi taskutietokoneen tehtävälistan KOrganizeriin.
+Comment[fr]=Ce canal synchronise la liste des tâches de votre Palm sur KOrganizer.
+Comment[fy]=Dit conduit syngronisearret de takenlist fan jo handheld mei KOrganizer.
+Comment[gl]=Este conducto sincroniza a lista de tarefas pendentes dende o seu aparello portátil a KOrganizer.
+Comment[hi]=यह कनà¥à¤¡à¥à¤¯à¥‚इट आपके हैंणà¥à¤¡à¤¹à¥‡à¤²à¥à¤¡ से टू-डू सूची को के-आरà¥à¤—ेनाइज़र में सिंक करता है
+Comment[hu]=Ezzel a csatolóval a Pilot tennivalólistája és a KOrganizer tennivalói között lehet szinkronizálást végezni.
+Comment[is]=Þessi rás samstillir verkþáttalista lófatölvunnar þinnar og KOrganizer.
+Comment[it]=Questo condotto sincronizza il tuo Pilot con la lista delle cose da fare di KOrganizer.
+Comment[ja]=ã“ã®ã‚³ãƒ³ã‚¸ãƒƒãƒˆã¯ãƒãƒ³ãƒ‰ãƒ˜ãƒ«ãƒ‰ã® To-Do 㨠KOrganizer ã‚’åŒæœŸã•ã›ã¾ã™ã€‚
+Comment[ka]=áƒáƒ›áƒáƒªáƒáƒœáƒáƒ—რსიების სინქრáƒáƒœáƒ˜áƒ–áƒáƒªáƒ˜áƒ KOrganizer-ისთვის.
+Comment[kk]=Қалта құрылғыдағы жоÑпар тізімін KOrganizer-мен қадамдаÑтыру арнаÑÑ‹.
+Comment[km]=បំពង់​នáŸáŸ‡â€‹áž’្វើ​សមកាលកម្ម​បញ្ជី​ការងារ​ážáŸ’រូវ​ធ្វើ​ពី​ឧបករណáŸâ€‹áž™áž½ážšâ€‹ážŠáŸƒâ€‹ážšáž”ស់​អ្នកទៅ KOrganizer ។
+Comment[lt]=Šis kanalas sinchronizuoja Jūsų darbų sąrašą iš delninuko su su KOrganizer sąrašu.
+Comment[ms]=Saluran ini mensegerakkan senarai tugasan dari komputer telapak anda ke KOrganizer.
+Comment[nb]=Denne kanalen synkroniserer gjørelista fra PDA-en til KOrganizer.
+Comment[nds]=Synkroniseert de Opgavenlist vun den Handreekner mit KOrganizer.
+Comment[ne]=यो कनà¥à¤¡à¤¯à¥à¤Ÿà¤²à¥‡ केडीई आयोजकमा हà¥à¤¯à¤¾à¤¨à¥à¤¡à¤¹à¥‡à¤²à¥à¤¡à¤¬à¤¾à¤Ÿ कारà¥à¤¯ गरà¥à¤¨à¥‡ सूचि सिनà¥à¤• गरà¥à¤¦à¤› ।
+Comment[nl]=Dit conduit synchroniseert de takenlijst van uw handheld met KOrganizer.
+Comment[nn]=Denne koplinga synkroniserer oppgåvelista frå den handheldte eininga di til KOrganizer.
+Comment[pl]=Ten łącznik synchronizuje listę zadań z palmtopa z KOrganizerem.
+Comment[pt]=Esta conduta sincroniza a lista de 'A Fazer' do seu dispositivo com o KOrganizer.
+Comment[pt_BR]=Este conduíte sincroniza a lista de tarefas do seu handheld com o KOrganizer.
+Comment[ru]=Канал Ñинхронизации ÑпиÑка задач КПК и органайзера KDE.
+Comment[sk]=Táto spojka synchronizuje zoznam ToDo s KOrganizer.
+Comment[sl]=Ta veznik usklajuje seznam ÄakajoÄih opravil z vaÅ¡ega roÄnega raÄunalnika s KOrganizerjem.
+Comment[sr]=Овај провод Ñинхронизује лиÑту обавеза из вашег ручног рачунара Ñа KOrganizer-ом.
+Comment[sr@Latn]=Ovaj provod sinhronizuje listu obaveza iz vaÅ¡eg ruÄnog raÄunara sa KOrganizer-om.
+Comment[sv]=Den här kanalen synkroniserar uppgiftslistan i handdatorn med Korganizer.
+Comment[ta]=இநà¯à®¤ காபà¯à®ªà¯à®•à¯à®•à¯à®´à®¾à®¯à¯ உஙà¯à®•à®³à¯ கையேடà¯à®Ÿà®¿à®²à¯ இரà¯à®¨à¯à®¤à¯ செயà¯à®¯à®µà¯‡à®£à¯à®Ÿà®¿à®¯ படà¯à®Ÿà®¿à®¯à®²à¯ˆ கேஅமைபாளரà¯à®•à¯à®•à¯ ஒதà¯à®¤à®¿à®šà¯ˆà®•à¯à®•à®¿à®±à®¤à¯
+Comment[tg]=Канали ÑинхронизатÑиÑи рӯйхати вазифоти Pilot ва органайзери KDE.
+Comment[tr]=Bu bileşen el bilgisayarınızdaki Yapılacaklar Listesini KOrganizer ile birleştirir.
+Comment[uk]=Цей акведук Ñинхронізує ÑпиÑок завдань кишенькового приÑтрою з тижневиком KOrganizer.
+Comment[zh_CN]=此管é“会将您的待办列表与 KOrganizer åŒæ­¥ã€‚
+Comment[zh_TW]=此軟體將您的 handheld 與 KOrganizer 的待辦事項清單åŒæ­¥ã€‚
+Name=ToDos (KOrganizer)
+Name[af]=Te-doen (KOrganizer)
+Name[ar]=الواجبات (KOrganizer)
+Name[be]=Заданні (K Ðрганізатар)
+Name[bg]=Задачи (KOrganizer)
+Name[br]=Traoù d'ober (KOrganizer)
+Name[bs]=Zadaci (KOrganizer)
+Name[ca]=Pendents (KOrganizer)
+Name[cs]=Úkoly (KOrganizer)
+Name[da]=Gøremål (KOrganizer)
+Name[de]=Aufgaben (KOrganizer)
+Name[el]=ΠÏος υλοποίηση εÏγασίες (KOrganizer)
+Name[eo]=Farendaĵoj (KOrganizilo)
+Name[es]=Tareas pendientes (KOrganizer)
+Name[et]=Ãœlesanded (KOrganizer)
+Name[eu]=Egitekoak (KOrganizer)
+Name[fa]=کارهای انجامی (KOrganizer)
+Name[fi]=Tehtävät (KOrganizer)
+Name[fr]=Tâches (KOrganizer)
+Name[fy]=Taken (KOrganizer)
+Name[ga]=Tascanna (KOrganizer)
+Name[gl]=Pendentes (KOrganizer)
+Name[he]=מטלות (×רגונית)
+Name[hu]=Feladatok (KOrganizer)
+Name[is]=Verkþáttalistar (KOrganizer)
+Name[it]=Cose da fare (KOrganizer)
+Name[ja]=To-Do (KOrganizer)
+Name[ka]=áƒáƒ›áƒáƒªáƒáƒœáƒ”ბი (KOrganizer)
+Name[kk]=ЖоÑпарлар (KOrganizer)
+Name[km]=ការងារ​ážáŸ’រូវ​ធ្វើ (KOrganizer)
+Name[lt]=Darbai (KOrganizer)
+Name[ms]=Tugsan (KOrganizer)
+Name[nb]=Gjøreliste (KOrganizer)
+Name[nds]=Opgaven (KOrganizer)
+Name[ne]=गरà¥à¤¨à¥à¤ªà¤°à¥à¤¨à¥‡ कारà¥à¤¯à¤¹à¤°à¥‚ (केडीई आयोजक)
+Name[nl]=Taken (KOrganizer)
+Name[nn]=Oppgåveliste (KOrganizer)
+Name[pl]=Do zrobienia (Korganizer)
+Name[pt]=Por Fazer (KOrganizer)
+Name[pt_BR]=Tarefas (KOrganizer)
+Name[ru]=Задачи (KOrganizer)
+Name[se]=Barggut (KOrganizer)
+Name[sk]=Úlohy (KOrganizer)
+Name[sl]=ÄŒakajoÄa opravila (KOrganizer)
+Name[sr]=Обавезе (KOrganizer)
+Name[sr@Latn]=Obaveze (KOrganizer)
+Name[sv]=Uppgifter (Korganizer)
+Name[ta]=செயà¯à®¯ வேணà¯à®Ÿà®¿à®¯à®µà¯ˆ(கேஅமைபà¯à®ªà®¾à®³à®°à¯)
+Name[tg]=Вазифот (KOrganizer)
+Name[tr]=Yapılacaklar (KOrganizer)
+Name[uk]=Ð—Ð°Ð²Ð´Ð°Ð½Ð½Ñ (KOrganizer)
+Name[zh_CN]=待办事项 (KOrganizer)
+Name[zh_TW]=待辦事項(KOrganizer)
+Implemented=file
+ServiceTypes=KPilotConduit
+X-KDE-Library=conduit_todo
diff --git a/kpilot/conduits/vcalconduit/todo-conduit.h b/kpilot/conduits/vcalconduit/todo-conduit.h
new file mode 100644
index 000000000..3364d61f2
--- /dev/null
+++ b/kpilot/conduits/vcalconduit/todo-conduit.h
@@ -0,0 +1,108 @@
+#ifndef _KPILOT_TODO_CONDUIT_H
+#define _KPILOT_TODO_CONDUIT_H
+/* todo-conduit.h KPilot
+**
+** Copyright (C) 2002-2003 Reinhold Kainhofer
+** Copyright (C) 1998-2001 Dan Pilone
+** Copyright (C) 1998-2000 Preston Brown <pbrown@kde.org>
+** Copyright (C) 1998 Herwin-Jan Steehouwer
+**
+** This file is part of the todo conduit, a conduit for KPilot that
+** synchronises the Pilot's todo application with the outside world,
+** which currently means KOrganizer.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include <libkcal/todo.h>
+#include <pilotTodoEntry.h>
+#include "vcal-conduitbase.h"
+
+class PilotSerialDatabase;
+class PilotLocalDatabase;
+
+class TodoConduitPrivate : public VCalConduitPrivateBase
+{
+public:
+ TodoConduitPrivate(KCal::Calendar *buddy);
+ virtual ~TodoConduitPrivate() {};
+
+ KCal::Todo::List fAllTodos;
+ KCal::Todo::List::ConstIterator fAllTodosIterator;
+
+ virtual int updateIncidences();
+ virtual void addIncidence(KCal::Incidence*);
+ virtual void removeIncidence(KCal::Incidence *);
+ virtual KCal::Incidence *findIncidence(recordid_t);
+ virtual KCal::Incidence *findIncidence(PilotRecordBase *tosearch);
+ virtual KCal::Incidence *getNextIncidence();
+ virtual KCal::Incidence *getNextModifiedIncidence();
+ virtual int count() {return fAllTodos.count();};
+} ;
+
+
+
+class TodoConduit : public VCalConduitBase
+{
+Q_OBJECT
+public:
+ TodoConduit(KPilotLink *,
+ const char *name=0L,
+ const QStringList &args = QStringList());
+ virtual ~TodoConduit();
+
+protected:
+ virtual const QString getTitle(PilotRecordBase *de);
+
+ virtual const QString dbname() { return CSL1("ToDoDB"); };
+ virtual void preSync();
+ virtual VCalConduitPrivateBase *createPrivateCalendarData(KCal::Calendar *fCalendar)
+ {
+ return new TodoConduitPrivate(fCalendar);
+ };
+
+ virtual void readConfig();
+ void _getAppInfo();
+ void _setAppInfo();
+ virtual void postSync();
+
+ virtual PilotRecordBase *newPilotEntry(PilotRecord*r)
+ {
+ return new PilotTodoEntry(r);
+ };
+ virtual KCal::Incidence*newIncidence() { return new KCal::Todo; };
+
+ virtual void preRecord(PilotRecord*r);
+ virtual VCalConduitSettings *config();
+public:
+ static VCalConduitSettings *theConfig();
+
+protected:
+
+ virtual PilotRecord *recordFromIncidence(PilotRecordBase *de, const KCal::Incidence *e);
+ virtual KCal::Incidence *incidenceFromRecord(KCal::Incidence *e, const PilotRecordBase *de);
+
+ PilotToDoInfo *fTodoAppInfo;
+ bool categoriesSynced;
+} ;
+
+#endif
diff --git a/kpilot/conduits/vcalconduit/todo-factory.cc b/kpilot/conduits/vcalconduit/todo-factory.cc
new file mode 100644
index 000000000..fad8841f2
--- /dev/null
+++ b/kpilot/conduits/vcalconduit/todo-factory.cc
@@ -0,0 +1,46 @@
+/* KPilot
+**
+** Copyright (C) 2002-2003 Reinhold Kainhofer
+** Copyright (C) 2001 by Dan Pilone
+**
+** This file defines the factory for the todo-conduit plugin.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include "options.h"
+
+#include "pluginfactory.h"
+
+#include "todo-setup.h"
+#include "todo-conduit.h"
+
+extern "C"
+{
+
+void *init_conduit_todo()
+{
+ return new ConduitFactory<ToDoWidgetSetup,TodoConduit>;
+}
+
+}
+
diff --git a/kpilot/conduits/vcalconduit/todo-factory.h b/kpilot/conduits/vcalconduit/todo-factory.h
new file mode 100644
index 000000000..52a2d5e4b
--- /dev/null
+++ b/kpilot/conduits/vcalconduit/todo-factory.h
@@ -0,0 +1,40 @@
+#ifndef _KPILOT_TODO_FACTORY_H
+#define _KPILOT_TODO_FACTORY_H
+/* todo-factory.h KPilot
+**
+** Copyright (C) 2002-2003 Reinhold Kainhofer
+** Copyright (C) 2001 by Dan Pilone
+**
+** This file defines the factory for the todo-conduit plugin.
+** It also defines the class for the behavior of the setup dialog.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+extern "C"
+{
+
+void *init_libtodoconduit();
+
+}
+
+#endif
diff --git a/kpilot/conduits/vcalconduit/todo-setup.cc b/kpilot/conduits/vcalconduit/todo-setup.cc
new file mode 100644
index 000000000..eb1c98c91
--- /dev/null
+++ b/kpilot/conduits/vcalconduit/todo-setup.cc
@@ -0,0 +1,86 @@
+/* KPilot
+**
+** Copyright (C) 2002-2003 Reinhold Kainhofer
+** Copyright (C) 2001 by Dan Pilone
+**
+** This file defines the factory for the todo-conduit plugin.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include "options.h"
+
+#include <qbuttongroup.h>
+#include <kaboutdata.h>
+
+#include "korganizerConduit.h"
+#include "todo-conduit.h"
+#include "todo-setup.h"
+
+
+
+ToDoWidgetSetup::ToDoWidgetSetup(QWidget *w, const char *n) :
+ VCalWidgetSetupBase(w,n)
+{
+ FUNCTIONSETUP;
+ fConduitName = i18n("To-do");
+ KAboutData *fAbout = new KAboutData("todoConduit",
+ I18N_NOOP("To-do Conduit for KPilot"),
+ KPILOT_VERSION,
+ I18N_NOOP("Configures the To-do Conduit for KPilot"),
+ KAboutData::License_GPL,
+ "(C) 2001, Adriaan de Groot\n(C) 2002-2003, Reinhold Kainhofer");
+ fAbout->addAuthor("Dan Pilone",
+ I18N_NOOP("Original Author"));
+ fAbout->addAuthor("Preston Brown",
+ I18N_NOOP("Original Author"));
+ fAbout->addAuthor("Herwin-Jan Steehouwer",
+ I18N_NOOP("Original Author"));
+ fAbout->addAuthor("Adriaan de Groot",
+ I18N_NOOP("Maintainer"),
+ "groot@kde.org",
+ "http://www.cs.kun.nl/~adridg/kpilot");
+ fAbout->addAuthor("Reinhold Kainhofer",
+ I18N_NOOP("Maintainer"),
+ "reinhold@kainhofer.com",
+ "http://reinhold.kainhofer.com/Linux/");
+
+ ConduitConfigBase::addAboutPage(fConfigWidget->tabWidget,fAbout);
+
+ fConfigWidget->fSyncDestination->setTitle(i18n("To-do Destination"));
+}
+
+ToDoWidgetSetup::~ToDoWidgetSetup()
+{
+ FUNCTIONSETUP;
+}
+
+/* static */ ConduitConfigBase *ToDoWidgetSetup::create(QWidget *w, const char *n)
+{
+ return new ToDoWidgetSetup(w,n);
+}
+
+VCalConduitSettings*ToDoWidgetSetup::config()
+{
+ return TodoConduit::theConfig();
+}
+
diff --git a/kpilot/conduits/vcalconduit/todo-setup.h b/kpilot/conduits/vcalconduit/todo-setup.h
new file mode 100644
index 000000000..9eebd3a3d
--- /dev/null
+++ b/kpilot/conduits/vcalconduit/todo-setup.h
@@ -0,0 +1,44 @@
+#ifndef _KPILOT_TODO_SETUP_H
+#define _KPILOT_TODO_SETUP_H
+/* todo-setup.h KPilot
+**
+** Copyright (C) 2002-2003 Reinhold Kainhofer
+** Copyright (C) 2001 by Dan Pilone
+**
+** This file defines the class for the behavior of the setup dialog.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include "vcal-setup.h"
+
+class ToDoWidgetSetup : public VCalWidgetSetupBase
+{
+public:
+ ToDoWidgetSetup(QWidget *,const char *);
+ virtual ~ToDoWidgetSetup();
+
+ virtual VCalConduitSettings*config();
+ static ConduitConfigBase *create(QWidget *, const char *);
+} ;
+
+#endif
diff --git a/kpilot/conduits/vcalconduit/todoRecord.cc b/kpilot/conduits/vcalconduit/todoRecord.cc
new file mode 100644
index 000000000..7db753fb5
--- /dev/null
+++ b/kpilot/conduits/vcalconduit/todoRecord.cc
@@ -0,0 +1,141 @@
+/* vcalRecord.cc KPilot
+**
+** Copyright (C) 2006 by Adriaan de Groot <groot@kde.org>
+** Copyright (C) 2002-2003 by Reinhold Kainhofer
+** Copyright (C) 2001 by Dan Pilone
+**
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include "options.h"
+
+#include <libkcal/calendar.h>
+#include <libkcal/calendarlocal.h>
+#include <libkcal/recurrence.h>
+#include <libkcal/vcalformat.h>
+
+#include "pilot.h"
+#include "pilotTodoEntry.h"
+
+#include "kcalRecord.h"
+#include "todoRecord.h"
+
+bool KCalSync::setTodoEntry(PilotTodoEntry *de,
+ const KCal::Todo *todo,
+ const CategoryAppInfo &info)
+{
+ FUNCTIONSETUP;
+ if (!de || !todo) {
+ DEBUGKPILOT << fname << ": NULL todo given... Skipping it" << endl;
+ return false;
+ }
+
+ // set secrecy, start/end times, alarms, recurrence, exceptions, summary and description:
+ if (todo->secrecy()!=KCal::Todo::SecrecyPublic)
+ {
+ de->setSecret( true );
+ }
+
+ // update it from the iCalendar Todo.
+
+ if (todo->hasDueDate()) {
+ struct tm t = writeTm(todo->dtDue());
+ de->setDueDate(t);
+ de->setIndefinite(0);
+ } else {
+ de->setIndefinite(1);
+ }
+
+ // TODO: take recurrence (code in VCAlConduit) from ActionNames
+
+ setCategory(de, todo, info);
+
+ // TODO: sync the alarm from ActionNames. Need to extend PilotTodoEntry
+ de->setPriority(todo->priority());
+
+ de->setComplete(todo->isCompleted());
+
+ // what we call summary pilot calls description.
+ de->setDescription(todo->summary());
+
+ // what we call description pilot puts as a separate note
+ de->setNote(todo->description());
+
+ DEBUGKPILOT << "-------- " << todo->summary() << endl;
+ return de->pack();
+}
+
+bool KCalSync::setTodo(KCal::Todo *e,
+ const PilotTodoEntry *de,
+ const CategoryAppInfo &info)
+{
+ FUNCTIONSETUP;
+
+ if (!e)
+ {
+ DEBUGKPILOT << fname
+ << ": null todo entry given. skipping..." << endl;
+ return false;
+ }
+ if (!de)
+ {
+ DEBUGKPILOT << fname
+ << "! NULL todo entry given... Skipping it" << endl;
+ return false;
+ }
+
+
+ e->setPilotId(de->id());
+ DEBUGKPILOT<<fname<<": set KCal item to pilotId: [" << e->pilotId() << "] ..."<<endl;
+
+ e->setSecrecy(de->isSecret() ? KCal::Todo::SecrecyPrivate : KCal::Todo::SecrecyPublic);
+
+ if (de->getIndefinite()) {
+ e->setHasDueDate(false);
+ } else {
+ e->setDtDue(readTm(de->getDueDate()));
+ e->setHasDueDate(true);
+ }
+
+ // Categories
+ setCategory(e, de, info);
+
+ // PRIORITY //
+ e->setPriority(de->getPriority());
+
+ // COMPLETED? //
+ e->setCompleted(de->getComplete());
+ if ( de->getComplete() && !e->hasCompletedDate() ) {
+ e->setCompleted( QDateTime::currentDateTime() );
+ }
+
+ e->setSummary(de->getDescription());
+ e->setDescription(de->getNote());
+
+ // NOTE: This MUST be done last, since every other set* call
+ // calls updated(), which will trigger an
+ // setSyncStatus(SYNCMOD)!!!
+ e->setSyncStatus(KCal::Incidence::SYNCNONE);
+
+ return true;
+}
diff --git a/kpilot/conduits/vcalconduit/todoRecord.h b/kpilot/conduits/vcalconduit/todoRecord.h
new file mode 100644
index 000000000..85ffd6aaf
--- /dev/null
+++ b/kpilot/conduits/vcalconduit/todoRecord.h
@@ -0,0 +1,49 @@
+#ifndef _KPILOT_TODORECORD_H
+#define _KPILOT_TODORECORD_H
+/*
+** Copyright (C) 2006 by Adriaan de Groot <groot@kde.org>
+** Copyright (C) 2002-2003 by Reinhold Kainhofer
+** Copyright (C) 2001 by Dan Pilone
+**
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+namespace KCal
+{
+ class Todo;
+}
+
+class PilotTodoEntry;
+
+namespace KCalSync
+{
+ bool setTodo(KCal::Todo *e,
+ const PilotTodoEntry *de,
+ const CategoryAppInfo &info);
+ bool setTodoEntry(PilotTodoEntry *de,
+ const KCal::Todo *e,
+ const CategoryAppInfo &info);
+}
+
+#endif
+
diff --git a/kpilot/conduits/vcalconduit/vcal-conduit.cc b/kpilot/conduits/vcalconduit/vcal-conduit.cc
new file mode 100644
index 000000000..0eea42733
--- /dev/null
+++ b/kpilot/conduits/vcalconduit/vcal-conduit.cc
@@ -0,0 +1,309 @@
+/* KPilot
+**
+** Copyright (C) 2002-2003 Reinhold Kainhofer
+** Copyright (C) 2001 by Dan Pilone
+**
+** This file defines the vcal-conduit plugin.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include "options.h"
+
+#include <libkcal/calendar.h>
+#include <libkcal/calendarlocal.h>
+#include <libkcal/recurrence.h>
+#include <libkcal/vcalformat.h>
+
+#include "pilotDateEntry.h"
+#include "pilotDatabase.h"
+
+#include "vcal-conduit.moc"
+#include "vcalconduitSettings.h"
+
+#include "kcalRecord.h"
+#include "vcalRecord.h"
+
+
+extern "C"
+{
+
+unsigned long version_conduit_vcal = Pilot::PLUGIN_API;
+
+}
+
+
+
+
+VCalConduitPrivate::VCalConduitPrivate(KCal::Calendar *b) :
+ VCalConduitPrivateBase(b)
+{
+ fAllEvents.setAutoDelete(false);
+}
+
+void VCalConduitPrivate::addIncidence(KCal::Incidence*e)
+{
+ fAllEvents.append(dynamic_cast<KCal::Event*>(e));
+ fCalendar->addEvent(dynamic_cast<KCal::Event*>(e));
+}
+
+int VCalConduitPrivate::updateIncidences()
+{
+ FUNCTIONSETUP;
+ if (!fCalendar) return 0;
+ fAllEvents = fCalendar->events();
+ fAllEvents.setAutoDelete(false);
+ return fAllEvents.count();
+}
+
+
+void VCalConduitPrivate::removeIncidence(KCal::Incidence *e)
+{
+ // use dynamic_cast which returns a null pointer if the class does not match...
+ fAllEvents.remove(dynamic_cast<KCal::Event*>(e));
+ if (!fCalendar) return;
+ fCalendar->deleteEvent(dynamic_cast<KCal::Event*>(e));
+ // now just in case we're in the middle of reading through our list
+ // and we delete something, set reading to false so we start at the
+ // top again next time and don't have problems with our iterator
+ reading = false;
+}
+
+
+KCal::Incidence *VCalConduitPrivate::findIncidence(recordid_t id)
+{
+ KCal::Event::List::ConstIterator it;
+ for( it = fAllEvents.begin(); it != fAllEvents.end(); ++it ) {
+ KCal::Event *event = *it;
+ if ((recordid_t)event->pilotId() == id) return event;
+ }
+ return 0L;
+}
+
+KCal::Incidence *VCalConduitPrivate::findIncidence(PilotRecordBase *tosearch)
+{
+ PilotDateEntry*entry=dynamic_cast<PilotDateEntry*>(tosearch);
+ if (!entry) return 0L;
+
+ QString title=entry->getDescription();
+ QDateTime dt=readTm( entry->getEventStart() );
+
+ KCal::Event::List::ConstIterator it;
+ for( it = fAllEvents.begin(); it != fAllEvents.end(); ++it ) {
+ KCal::Event *event = *it;
+ if ( (event->dtStart() == dt) && (event->summary() == title) ) return event;
+ }
+ return 0L;
+}
+
+
+
+KCal::Incidence *VCalConduitPrivate::getNextIncidence()
+{
+ FUNCTIONSETUP;
+
+ if (reading) {
+ ++fAllEventsIterator;
+ } else {
+ reading=true;
+ fAllEventsIterator = fAllEvents.begin();
+ }
+ // At end of list, or empty list.
+ return (fAllEventsIterator == fAllEvents.end()) ? 0L : *fAllEventsIterator;
+}
+
+/** Find the next incidence in the list which ddoes not have the SYNCNONE flag set. The
+ * current position is always stored in the iteratoor fAllEventsIterator, so we can just
+ * start from there. Only if reading==false, we haven't yet started goind through the
+ * incidents, so start at fAllEvents.begin() in that case */
+KCal::Incidence *VCalConduitPrivate::getNextModifiedIncidence()
+{
+ FUNCTIONSETUP;
+ KCal::Event*e=0L;
+ if (!reading)
+ {
+ // Start from the top
+ reading=true;
+ fAllEventsIterator = fAllEvents.begin();
+ }
+ else
+ {
+ // Move on from current position
+ ++fAllEventsIterator;
+ }
+
+ // Fetch (new) current if possible.
+ if ( fAllEventsIterator != fAllEvents.end() ) e = *fAllEventsIterator;
+ // Then walk the list until we find an unsynced entry
+ while ( fAllEventsIterator != fAllEvents.end() &&
+ e && e->syncStatus()!=KCal::Incidence::SYNCMOD && e->pilotId() > 0)
+ {
+ e = (++fAllEventsIterator != fAllEvents.end()) ? *fAllEventsIterator : 0L;
+ }
+ return (fAllEventsIterator == fAllEvents.end()) ? 0L : *fAllEventsIterator;
+}
+
+
+
+/****************************************************************************
+ * VCalConduit class *
+ ****************************************************************************/
+
+VCalConduit::VCalConduit(KPilotLink *d,
+ const char *n,
+ const QStringList &a) :
+ VCalConduitBase(d,n,a),
+ fAppointmentAppInfo( 0L )
+{
+ FUNCTIONSETUP;
+ fConduitName=i18n("Calendar");
+}
+
+
+VCalConduit::~VCalConduit()
+{
+// FUNCTIONSETUP;
+}
+
+VCalConduitPrivateBase *VCalConduit::createPrivateCalendarData(KCal::Calendar *fCalendar) {
+ return new VCalConduitPrivate(fCalendar);
+}
+
+void VCalConduit::_getAppInfo()
+{
+ FUNCTIONSETUP;
+ // get the address application header information
+ KPILOT_DELETE(fAppointmentAppInfo);
+ fAppointmentAppInfo = new PilotDateInfo( fDatabase );
+}
+
+const QString VCalConduit::getTitle(PilotRecordBase *de)
+{
+ PilotDateEntry*d=dynamic_cast<PilotDateEntry*>(de);
+ if (d) return QString(d->getDescription());
+ return QString::null;
+}
+
+
+
+PilotRecord *VCalConduit::recordFromIncidence(PilotRecordBase *de, const KCal::Incidence*e)
+{
+ FUNCTIONSETUP;
+ if (!de || !e)
+ {
+ DEBUGKPILOT << fname
+ << ": got NULL entry or NULL incidence." << endl;
+ return 0L;
+ }
+
+ if ( (e->recurrenceType() == KCal::Recurrence::rYearlyDay) ||
+ (e->recurrenceType() == KCal::Recurrence::rYearlyPos) )
+ {
+ // Warn ahead of time
+ emit logMessage(i18n("Event \"%1\" has a yearly recurrence other than by month, will change this to recurrence by month on handheld.").arg(e->summary()));
+ }
+
+ PilotDateEntry *dateEntry = dynamic_cast<PilotDateEntry*>(de);
+ if (!dateEntry)
+ {
+ // Secretly wasn't a date entry after all
+ return 0L;
+ }
+
+ const KCal::Event *event = dynamic_cast<const KCal::Event *>(e);
+ if (!event)
+ {
+ DEBUGKPILOT << fname << ": Incidence is not an event." << endl;
+ return 0L;
+ }
+
+ if (KCalSync::setDateEntry(dateEntry, event,*fAppointmentAppInfo->categoryInfo()))
+ {
+ return dateEntry->pack();
+ }
+ else
+ {
+ return 0L;
+ }
+}
+
+KCal::Incidence *VCalConduit::incidenceFromRecord(KCal::Incidence *e, const PilotRecordBase *de)
+{
+ FUNCTIONSETUP;
+
+ if (!de || !e)
+ {
+ DEBUGKPILOT << fname
+ << ": Got NULL entry or NULL incidence." << endl;
+ return 0L;
+ }
+
+ const PilotDateEntry *dateEntry = dynamic_cast<const PilotDateEntry *>(de);
+ if (!dateEntry)
+ {
+ DEBUGKPILOT << fname << ": HH record not a date entry." << endl;
+ return 0L;
+ }
+
+ KCal::Event *event = dynamic_cast<KCal::Event *>(e);
+ if (!event)
+ {
+ DEBUGKPILOT << fname << ": Incidence is not an event." << endl;
+ return 0L;
+ }
+
+ KCalSync::setEvent(event, dateEntry,*fAppointmentAppInfo->categoryInfo());
+ return e;
+}
+
+
+
+PilotRecordBase * VCalConduit::newPilotEntry(PilotRecord*r)
+{
+ return new PilotDateEntry(r);
+}
+
+KCal::Incidence* VCalConduit::newIncidence()
+{
+ return new KCal::Event;
+}
+
+static VCalConduitSettings *config_vcal = 0L;
+
+VCalConduitSettings *VCalConduit::theConfig()
+{
+ if (!config_vcal)
+ {
+ config_vcal = new VCalConduitSettings(CSL1("Calendar"));
+ }
+
+ return config_vcal;
+}
+
+VCalConduitSettings *VCalConduit::config() {
+ return theConfig();
+}
+
+
+
+// vim: ts=4:sw=4:noexpandtab:
+
diff --git a/kpilot/conduits/vcalconduit/vcal-conduit.desktop b/kpilot/conduits/vcalconduit/vcal-conduit.desktop
new file mode 100644
index 000000000..e0a84c55f
--- /dev/null
+++ b/kpilot/conduits/vcalconduit/vcal-conduit.desktop
@@ -0,0 +1,105 @@
+[Desktop Entry]
+Type=Service
+Name=Calendar (KOrganizer)
+Name[af]=Kalender (KOrganizer)
+Name[ar]=التقويم (KOrganizer)
+Name[be]=КалÑндар (K Ðрганізатар)
+Name[bg]=Календар (KOrganizer)
+Name[br]=Deiziadur (KOrganizer)
+Name[bs]=Kalendar (KOrganizer)
+Name[ca]=Calendari (KOrganizer)
+Name[cs]=Kalendář (KOrganizer)
+Name[da]=Kalender (KOrganizer)
+Name[de]=Kalender (KOrganizer)
+Name[el]=ΗμεÏολόγιο (KOrganizer)
+Name[eo]=Kalendaro (KOrganizilo)
+Name[es]=Calendario (KOrganizer)
+Name[et]=Kalender (KOrganizer)
+Name[eu]=Egutegia (KOrganizer)
+Name[fa]=تقویم (KOrganizer)
+Name[fi]=Kalenteri (KOrganizer)
+Name[fr]=Agenda (KOrganizer)
+Name[fy]=Aginda (KOrganizer)
+Name[ga]=Féilire (KOrganizer)
+Name[gl]=Calendario (KOrganizer)
+Name[he]=לוח שנה (×רגונית)
+Name[hu]=Naptár (KOrganizer)
+Name[is]=Dagbók (KOrganizer)
+Name[it]=Calendario (KOrganizer)
+Name[ja]=カレンダー (KOrganizer)
+Name[ka]=კáƒáƒšáƒ”ნდáƒáƒ áƒ˜ (KOrganizer)
+Name[kk]=Күнтізбе (KOrganizer)
+Name[km]=ប្រážáž·áž‘áž·áž“ (KOrganizer)
+Name[lt]=Kalendorius (KOrganizer)
+Name[mk]=Календар (КОрганизатор)
+Name[ms]=Kalendar (KOrganizer)
+Name[nb]=Kalender (KOrganizer)
+Name[nds]=Kalenner (KOrganizer)
+Name[ne]=कà¥à¤¯à¤¾à¤²à¥‡à¤¨à¥à¤¡à¤° (केडीई आयोजक)
+Name[nl]=Agenda (KOrganizer)
+Name[nn]=Kalender (KOrganizer)
+Name[pl]=Kalendarz (Korganizer)
+Name[pt]=Calendário (KOrganizer)
+Name[pt_BR]=Calendário (KOrganizer)
+Name[ru]=Календарь (KOrganizer)
+Name[se]=Kaleandar (KOrganizer)
+Name[sk]=Kalendár (KOrganizer)
+Name[sl]=Koledar (KOrganizer)
+Name[sr]=Календар (KOrganizer)
+Name[sr@Latn]=Kalendar (KOrganizer)
+Name[sv]=Kalender (Korganizer)
+Name[ta]=நாளà¯à®•à®¾à®Ÿà¯à®Ÿà®¿(கேஅமைபà¯à®ªà®¾à®³à®°à¯)
+Name[tg]=Тақвимот (KOrganizer)
+Name[tr]=Takvim (KOrganizer)
+Name[uk]=Календар (KOrganizer)
+Name[zh_CN]=日历 (KOrganizer)
+Name[zh_TW]=行事曆(KOrganizer)
+Comment=This conduit synchronizes your handheld with the KOrganizer datebook.
+Comment[af]=Hierdie pad sinkroniseer jou draagbare toestel met die KOrganizer datum boek.
+Comment[bg]=Ð¡Ð¸Ð½Ñ…Ñ€Ð¾Ð½Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð½Ð° календара на мобилно уÑтройÑтво Ñ Ð¾Ñ€Ð³Ð°Ð½Ð¸Ð·Ð°Ñ‚Ð¾Ñ€Ð° в KDE.
+Comment[ca]=Aquest conducte sincronitza la vostra agenda electrònica amb la llibreta de dates de KOrganizer.
+Comment[cs]=Toto propojení synchronizuje seznam úkolů s KOrganizérem.
+Comment[da]=Denne kanal synkroniserer din håndholdte med KOrganizer-datobogen.
+Comment[de]=Abgleich des Taschencomputers mit dem KOrganizer-Terminkalender
+Comment[el]=Αυτός ο σÏνδεσμος συγχÏονίζει τον υπολογιστή παλάμης σας με το βιβλίο ημεÏομηνιών του KOrganizer.
+Comment[en_GB]=This conduit synchronises your handheld with the KOrganizer datebook.
+Comment[eo]=Tiu kanalo sinkronigas vian poÅkomputilon kun la datlibro de KOrganizilo.
+Comment[es]=Este conducto sincroniza su agenda electrónica con la libreta de fechas de KOrganizer.
+Comment[et]=See kanal sünkroniseerib pihuseadme ja KOrganizeri kalendri.
+Comment[eu]=Kanal honek zure agenda elektronikoa KOrganizer-en data-liburuarekin sinkronizatzen du.
+Comment[fa]=این لوله، دستی شما را با کتاب دادۀ KOrganizer همگام می‌سازد.
+Comment[fi]=Tämä yhdyskäytävä synkronoi taskutietokoneen KOrganizerin päiväkirjaan.
+Comment[fr]=Ce canal synchronise votre Palm avec l'agenda KOrganizer.
+Comment[fy]=Dit conduit syngronisearret jo handheld mei KOrganizer's datumboek.
+Comment[gl]=Este conducto sincroniza o seu aparello portátil co libro de datos de KOrganizer.
+Comment[hu]=Ezzel a csatolóval szinkronizálhatók a kézi számítógép és a KOrganizer dátumai.
+Comment[is]=Þessi rás samstillir lófatölvuna þína við dagbók KOrganizer.
+Comment[it]=Questo conduit sincronizza il tuo palmare con il calendario di KOrganizer.
+Comment[ja]=ã“ã®ã‚³ãƒ³ã‚¸ãƒƒãƒˆã¯ãƒãƒ³ãƒ‰ãƒ˜ãƒ«ãƒ‰ã‚’ KOrganizer ã®æ‰‹å¸³ã¨åŒæœŸã•ã›ã¾ã™ã€‚
+Comment[ka]=სინქრáƒáƒœáƒ˜áƒ–áƒáƒªáƒ˜áƒ KOrganizer-ისთვის.
+Comment[kk]=Қалта құрылғыдағы күнтізбені KOrganizer-мен қадамдаÑтыру арнаÑÑ‹.
+Comment[km]=បំពង់​នáŸáŸ‡â€‹áž’្វើ​សមកាលកម្ម​ឧបករណáŸâ€‹áž™áž½ážšâ€‹ážŠáŸƒâ€‹ážšáž”ស់​អ្នក​ជាមួយ​នឹង​សៀវភៅ​កាលបរិច្ឆáŸáž‘ KOrganizer ។
+Comment[lt]=Šis kanalas sinchronizuoja jūsų delninuką su KOrganizer datų knyga.
+Comment[mk]=Овој канал ги Ñинхронизира рачниот уред и датумите од KОрганизатор.
+Comment[ms]=Saluran ini mensegerakkan komputer telapak dengan buku tarikh KOrganizer.
+Comment[nb]=Denne kanalen synkroniserer PDA-en med KOrganizers almanakk.
+Comment[nds]=Synkroniseert den Mötenkalenner vun den Handreekner mit KOrganizer.
+Comment[ne]=यो कनà¥à¤¡à¥à¤¯à¥à¤Ÿà¤²à¥‡ केडीई आयोजक मिति पà¥à¤¸à¥à¤¤à¤¿à¤•à¤¾à¤®à¤¾ हà¥à¤¯à¤¾à¤¨à¥à¤¡à¤¹à¥‡à¤²à¥à¤¡ समकà¥à¤°à¤®à¤£ गरà¥à¤› ।
+Comment[nl]=Dit conduit synchroniseert uw handheld met KOrganizer's datumboek.
+Comment[pl]=Ten Å‚Ä…cznik synchronizuje palmtopa z terminarzem KOrganizera.
+Comment[pt]=Esta conduta sincroniza o seu dispositivo móvel com a agenda do KOrganizer.
+Comment[pt_BR]=Este Conduíte sincroniza seu handheld com a agenda do KOrganizer.
+Comment[ru]=Канал Ñинхронизации ÐºÐ°Ð»ÐµÐ½Ð´Ð°Ñ€Ñ ÐšÐŸÐš и органайзера KDE.
+Comment[sk]=Táto spojka synchronizuje prenosné zariadenie s KOrganizer.
+Comment[sl]=Ta veznik uskladni vaÅ¡ roÄni raÄunalnik z dnevnikom KOrganizerja.
+Comment[sr]=Овај провод Ñинхронизује ваш ручни рачунар Ñа KOrganizer-овом књигом датума.
+Comment[sr@Latn]=Ovaj provod sinhronizuje vaÅ¡ ruÄni raÄunar sa KOrganizer-ovom knjigom datuma.
+Comment[sv]=Den här kanalen synkroniserar din handdator med Korganizers kalender.
+Comment[ta]=இநà¯à®¤ கà¯à®´à®¾à®¯à¯ உஙà¯à®•à®³à¯ பைலடà¯à®Ÿà¯ˆ கேஅமைபà¯à®ªà®¾à®³à®°à¯ தேதிபà¯à®¤à¯à®¤à®•à®¤à¯à®¤à¯à®Ÿà®©à¯ ஒதà¯à®¤à®¿à®šà¯ˆà®•à¯à®•à®¿à®±à®¤à¯
+Comment[tr]=Bu bileşen el bilgisayarınızı KOrganizer'daki randevu defteriyle senkronize eder.
+Comment[uk]=Цей акведук Ñинхронізує ваш кишеньковий приÑтрій з тижневиком KOrganizer.
+Comment[zh_CN]=此管é“会将您的手æŒè®¾å¤‡ä¸Ž KOrganizer 的日程安排åŒæ­¥ã€‚
+Comment[zh_TW]=此軟體將您的 handheld 日期與 KOrganizer åŒæ­¥ã€‚
+Implemented=file
+ServiceTypes=KPilotConduit
+X-KDE-Library=conduit_vcal
diff --git a/kpilot/conduits/vcalconduit/vcal-conduit.h b/kpilot/conduits/vcalconduit/vcal-conduit.h
new file mode 100644
index 000000000..c41ceb906
--- /dev/null
+++ b/kpilot/conduits/vcalconduit/vcal-conduit.h
@@ -0,0 +1,101 @@
+#ifndef _KPILOT_VCAL_CONDUIT_H
+#define _KPILOT_VCAL_CONDUIT_H
+/* vcal-conduit.h KPilot
+**
+** Copyright (C) 2002-2003 Reinhold Kainhofer
+** Copyright (C) 2001 by Dan Pilone
+**
+** This file defines the vcal-conduit plugin.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include <libkcal/event.h>
+
+#include "pilotDateEntry.h"
+
+#include "vcal-conduitbase.h"
+
+class PilotRecord;
+class PilotSerialDatabase;
+class PilotLocalDatabase;
+
+class VCalConduitPrivate : public VCalConduitPrivateBase
+{
+public:
+ VCalConduitPrivate(KCal::Calendar *buddy);
+ virtual ~VCalConduitPrivate() {};
+
+ KCal::Event::List fAllEvents;
+ KCal::Event::List::ConstIterator fAllEventsIterator;
+
+ virtual int updateIncidences();
+ virtual void addIncidence(KCal::Incidence*);
+ virtual void removeIncidence(KCal::Incidence *);
+ virtual KCal::Incidence *findIncidence(recordid_t);
+ /**
+ * Find the incidence based on tosearch's description and date information.
+ * Returns 0L if no incidence could be found.
+ */
+ virtual KCal::Incidence *findIncidence(PilotRecordBase *tosearch);
+ virtual KCal::Incidence *getNextIncidence();
+ virtual KCal::Incidence *getNextModifiedIncidence();
+ virtual int count() {return fAllEvents.count();};
+} ;
+
+
+
+class VCalConduit : public VCalConduitBase
+{
+Q_OBJECT
+public:
+ VCalConduit(KPilotLink *,
+ const char *name=0L,
+ const QStringList &args = QStringList());
+ virtual ~VCalConduit();
+
+protected:
+ virtual const QString dbname() { return CSL1("DatebookDB"); };
+
+ virtual void preSync() {VCalConduitBase::preSync(); _getAppInfo(); };
+ virtual VCalConduitPrivateBase *createPrivateCalendarData(KCal::Calendar *fCalendar);
+
+ void _getAppInfo();
+ void _setAppInfo();
+
+ virtual PilotRecordBase *newPilotEntry(PilotRecord*r);
+ virtual KCal::Incidence*newIncidence();
+ virtual const QString getTitle(PilotRecordBase *de);
+ virtual VCalConduitSettings *config();
+public:
+ static VCalConduitSettings *theConfig();
+
+protected:
+ virtual PilotRecord *recordFromIncidence(PilotRecordBase *de,
+ const KCal::Incidence *e);
+ virtual KCal::Incidence *incidenceFromRecord(KCal::Incidence *e,
+ const PilotRecordBase *de);
+
+ PilotDateInfo *fAppointmentAppInfo;
+};
+
+#endif
diff --git a/kpilot/conduits/vcalconduit/vcal-conduitbase.cc b/kpilot/conduits/vcalconduit/vcal-conduitbase.cc
new file mode 100644
index 000000000..a9fc6376b
--- /dev/null
+++ b/kpilot/conduits/vcalconduit/vcal-conduitbase.cc
@@ -0,0 +1,622 @@
+/* KPilot
+**
+** Copyright (C) 2002-3 by Reinhold Kainhofer
+** Copyright (C) 2001 by Dan Pilone
+**
+** Contributions:
+** Copyright (c) 2001 David Jarvie <software@astrojar.org.uk>
+** Copyright (C) 2006 by Bertjan Broeksema <b.broeksema@gmail.com>
+**
+** This file defines the vcal-conduit plugin.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include <options.h>
+
+#include <qtimer.h>
+#include <qfile.h>
+
+#include <kmessagebox.h>
+#include <kio/netaccess.h>
+
+#include "libkcal/calendar.h"
+#include "libkcal/calendarlocal.h"
+#include "libkcal/calendarresources.h"
+#include <kstandarddirs.h>
+
+#include "pilotSerialDatabase.h"
+#include "pilotLocalDatabase.h"
+#include "pilotDateEntry.h"
+
+#include "vcal-conduitbase.moc"
+#include "vcalconduitSettings.h"
+
+#ifndef LIBKCAL_IS_VERSION
+#warning "Using an old version of libkcal with timezone bug."
+#define LIBKCAL_IS_VERSION(a,b,c) (0)
+#endif
+
+#include "conduitstate.h"
+#include "initstate.h"
+
+
+/****************************************************************************
+ * VCalConduitBase class *
+ ****************************************************************************/
+
+VCalConduitBase::VCalConduitBase(KPilotLink *d,
+ const char *n,
+ const QStringList &a) :
+ ConduitAction(d,n,a),
+ fCalendar(0L),
+ fP(0L)
+{
+ FUNCTIONSETUP;
+
+ fState = new InitState();
+}
+
+VCalConduitBase::~VCalConduitBase()
+{
+ FUNCTIONSETUP;
+
+ KPILOT_DELETE(fP);
+ KPILOT_DELETE(fState);
+ KPILOT_DELETE(fCalendar);
+ KPILOT_DELETE(fDatabase);
+ KPILOT_DELETE(fLocalDatabase);
+}
+
+
+/*
+ There are several different scenarios for a record on the Palm and its PC
+ counterpart. N means a new record, M flags a modified record, D a deleted
+ and - an unmodified record. First is the Palm record, second the
+ corresponding PC record:
+ (-,-) unchanged, just sync if first time or full sync
+ (N,-) no rec matching the Palm ID in the backupDB/calendar yet => add
+ KCal::Event
+ (M,-) record is in backupDB, unchanged in calendar => modify in calendar and
+ in backupDB
+ (D,-) deleted on Palm, exists in backupDB and calendar => just delete from
+ calendar and backupDB
+ (-,N) no or invalid pilotID set for the KCal::Event => just add to palm and
+ backupDB
+ (-,M) valid PilotID set => just modify on Palm
+ (-,D) Record in backupDB, but not in calendar => delete from Palm and
+ backupDB
+ (N,N) Can't find out (the two records are not correlated in any way, they
+ just have the same data!!
+ (M,M),(M,L),(L,M) (Record exists on Palm and the Event has the ID) CONFLICT,
+ ask the user what to do or use a config setting
+ (L,L) already deleted on both, no need to do anything.
+
+ The sync process is as follows (for a fast sync):
+ 1) HHToPCState goes through all records on Palm (just the modified one
+ are necessary), find it in the backupDB. The following handles ([NMD],*)
+ a) if it doesn't exist and was not deleted, add it to the calendar and
+ the backupDB
+ b) if it exists, is unchanged in the calendar and was not deleted,
+ just modify in the calendar
+ c) if it exists and was deleted, delete it from the calendar if
+ necessary
+ 2) PCToHHState goes through all KCale::Events in the calendar (just
+ modified, this is the modification time is later than the last sync time
+ ). This handles (-,N),(-,M)
+ a) if it does not have a pilotID, add it to the palm and backupDB,
+ store the PalmID
+ b) if it has a valid pilotID, update the Palm record and the backup
+ 3) DeletedUnsyncedHHState goes through all palm records (which don't
+ have the deleted flag) of the palm db and if one does not exist in the
+ Calendar, it was deleted there, so delete it from the Palm and backup,
+ too. This handles the case of (-,D)
+ 4) DeletedUnsyncedPCState goes through all KCal::Events in the calendar and
+ looks for a corresponding event in the palm database. If it does not
+ exist, that means that it was deleted on the palm, so we need to also
+ delete it from the local calendar. This handles the case of (D,-).
+
+ In addition to the fast sync, where the last sync was done with this very
+ PC and calendar file, there are two special cases: a full and a first sync.
+ -) a full sync goes through all records, not just the modified ones. The
+ pilotID setting of the calendar records is used to determine if the
+ record already exists. if yes, the record is just modified.
+ -) a first sync completely ignores the pilotID setting of the calendar
+ events. All records are added, so there might be duplicates. The add
+ function for the calendar should check if a similar record already
+ exists, but this is not done yet.
+
+ -) a full sync is done if
+ a) there is a backupdb and a calendar, but the PC id number changed
+ b) it was explicitly requested by pressing the full sync button in KPilot
+ c) the setting "always full sync" was selected in the configuration dlg
+ -) a first sync is done if
+ a) either the calendar or the backup DB does not exist.
+ b) the calendar and the backup DB exists, but the sync is done for a
+ different User name
+ c) it was explicitly requested in KPilot
+*/
+
+/* virtual */ bool VCalConduitBase::exec()
+{
+ FUNCTIONSETUP;
+
+ readConfig();
+
+ // don't do a first sync by default in any case, only when explicitly
+ // requested, or the backup database or the alendar are empty.
+ setFirstSync( false );
+
+ // TODO: Check Full sync and First sync
+ bool retrieved = false;
+ if ( !openDatabases( dbname(), &retrieved ) ) goto error;
+ setFirstSync( retrieved );
+
+ // If we are in testmode we don't need the local calendar. Else a
+ // calendar *must* be opened, we want to sync something don't we?
+ if (!syncMode().isTest() && !openCalendar() ) goto error;
+
+ // Start processing the sync
+ QTimer::singleShot(0, this, SLOT(slotProcess()));
+ return true;
+
+error:
+ emit logError( i18n( "Could not open the calendar databases." ) );
+
+ KPILOT_DELETE(fCalendar);
+ KPILOT_DELETE(fP);
+ KPILOT_DELETE(fState);
+ return false;
+}
+
+void VCalConduitBase::slotProcess() {
+ FUNCTIONSETUP;
+
+ // start the current state if necessary
+ if( fState && !fState->started() ) {
+ fState->startSync( this );
+ }
+
+ // Process next record if applicable
+ if( hasNextRecord )
+ {
+ fState->handleRecord( this );
+ QTimer::singleShot( 0, this, SLOT( slotProcess() ) );
+ }
+ // Else finish the current state if there is one
+ else if( fState )
+ {
+ fState->finishSync( this );
+ QTimer::singleShot( 0, this, SLOT( slotProcess() ) );
+ }
+ // No state so sync is finished
+ else
+ {
+ DEBUGKPILOT << fname << ": Sync finished." << endl;
+ delayDone();
+ }
+}
+
+/* virtual */ void VCalConduitBase::readConfig()
+{
+ config()->readConfig();
+ SyncAction::ConflictResolution res = (SyncAction::ConflictResolution)
+ (config()->conflictResolution());
+ setConflictResolution( res );
+}
+
+static void listResources( KCal::CalendarResources *p )
+{
+ FUNCTIONSETUP;
+ KCal::CalendarResourceManager *manager = p->resourceManager();
+
+ DEBUGKPILOT << fname << ": Resources in calendar:" << endl;
+ KCal::CalendarResourceManager::Iterator it;
+ for( it = manager->begin(); it != manager->end(); ++it )
+ {
+ DEBUGKPILOT << fname << ": " << (*it)->resourceName() << endl;
+ }
+}
+
+/* virtual */ bool VCalConduitBase::openCalendar()
+{
+ FUNCTIONSETUP;
+
+ KConfig korgcfg( locate( "config", CSL1("korganizerrc") ) );
+
+ // this part taken from adcalendarbase.cpp:
+ korgcfg.setGroup( "Time & Date" );
+ QString tz(korgcfg.readEntry( "TimeZoneId" ) );
+
+ DEBUGKPILOT << fname << ": KOrganizer's time zone = " << tz << endl;
+
+ // Need a subclass ptr. for the ResourceCalendar methods
+ KCal::CalendarResources *rescal = 0L;
+
+ DEBUGKPILOT << fname << ": Got calendar type " << config()->calendarType()
+ << endl;
+
+ switch(config()->calendarType())
+ {
+ case VCalConduitSettings::eCalendarLocal:
+ {
+ DEBUGKPILOT << fname << "Using CalendarLocal, file = "
+ << config()->calendarFile() << endl;
+
+ if ( config()->calendarFile().isEmpty() )
+ {
+ DEBUGKPILOT << fname << "Empty calendar file name." << endl;
+
+ emit logError( i18n( "You selected to sync with an iCalendar"
+ " file, but did not give a filename. Please select a"
+ " valid file name in the conduit's configuration"
+ " dialog" ) );
+ return false;
+ }
+
+ fCalendar = new KCal::CalendarLocal( tz );
+ if ( !fCalendar )
+ {
+ WARNINGKPILOT
+ << "Cannot initialize calendar object for file "
+ << config()->calendarFile() << endl;
+ return false;
+ }
+
+ DEBUGKPILOT << fname << "Calendar's timezone: "
+ << fCalendar->timeZoneId() << endl;
+ DEBUGKPILOT << fname << "Calendar is local time: "
+ << fCalendar->isLocalTime() << endl;
+
+ emit logMessage( fCalendar->isLocalTime() ?
+ i18n( "Using local time zone: %1" ).arg( tz ) :
+ i18n( "Using non-local time zone: %1" ).arg( tz ) );
+
+ KURL kurl( config()->calendarFile() );
+ if( !KIO::NetAccess::download( config()->calendarFile(),
+ fCalendarFile, 0L ) && !kurl.isLocalFile() )
+ {
+ emit logError(i18n( "You chose to sync with the file \"%1\", which "
+ "cannot be opened. Please make sure to supply a "
+ "valid file name in the conduit's configuration dialog. "
+ "Aborting the conduit." ).arg( config()->calendarFile() ) );
+ KIO::NetAccess::removeTempFile( fCalendarFile );
+ return false;
+ }
+
+ // if there is no calendar yet, use a first sync..
+ // the calendar is initialized, so nothing more to do...
+ if (!dynamic_cast<KCal::CalendarLocal*>(fCalendar)->load(fCalendarFile) )
+ {
+ DEBUGKPILOT << fname << "Calendar file " << fCalendarFile
+ << " could not be opened. Will create a new one" << endl;
+
+ // Try to create empty file. if it fails,
+ // no valid file name was given.
+ QFile fl(fCalendarFile);
+ if (!fl.open(IO_WriteOnly | IO_Append))
+ {
+ DEBUGKPILOT << fname << "Invalid calendar file name "
+ << fCalendarFile << endl;
+
+ emit logError( i18n( "You chose to sync with the file \"%1\", which "
+ "cannot be opened or created. Please make sure to supply a "
+ "valid file name in the conduit's configuration dialog. "
+ "Aborting the conduit." ).arg( config()->calendarFile() ) );
+ return false;
+ }
+ fl.close();
+ setFirstSync( true );
+ }
+ addSyncLogEntry( i18n( "Syncing with file \"%1\"" )
+ .arg( config()->calendarFile() ) );
+ break;
+ }
+
+ case VCalConduitSettings::eCalendarResource:
+ DEBUGKPILOT << "Using CalendarResource!" << endl;
+
+ rescal = new KCal::CalendarResources( tz );
+ listResources(rescal);
+ fCalendar = rescal;
+ if ( !fCalendar)
+ {
+ WARNINGKPILOT << "Cannot initialize calendar " <<
+ "object for ResourceCalendar" << endl;
+ return false;
+ }
+
+#if LIBKCAL_IS_VERSION(1,1,0)
+ rescal->readConfig();
+ rescal->load();
+#else
+#warning "Timezone bug is present."
+#endif
+ addSyncLogEntry( i18n( "Syncing with standard calendar resource." ) );
+ emit logMessage( fCalendar->isLocalTime() ?
+ i18n( "Using local time zone: %1" ).arg( tz ) :
+ i18n( "Using non-local time zone: %1" ).arg( tz ) );
+ break;
+ default:
+ break;
+ }
+
+ if ( !fCalendar )
+ {
+ WARNINGKPILOT << "Unable to initialize calendar object."
+ << " Please check the conduit's setup." << endl;
+ emit logError( i18n( "Unable to initialize the calendar object. Please"
+ " check the conduit's setup") );
+ return false;
+ }
+ fP = createPrivateCalendarData( fCalendar );
+ if ( !fP )
+ {
+ return false;
+ }
+ int rc = fP->updateIncidences();
+ DEBUGKPILOT << fname << ": return from updateIncidences: [" << rc
+ << "]" << endl;
+
+ if ( fP->count() < 1 )
+ {
+ setFirstSync( true );
+ }
+
+ return true;
+}
+
+KCal::Incidence* VCalConduitBase::addRecord( PilotRecord *r )
+{
+ FUNCTIONSETUP;
+
+ recordid_t id = fLocalDatabase->writeRecord( r );
+ DEBUGKPILOT<<fname<<": Pilot Record ID = " << r->id() << ", backup ID = "
+ << id << endl;
+
+ PilotRecordBase *de = newPilotEntry( r );
+ KCal::Incidence*e = 0L;
+
+ if ( de )
+ {
+ e = fP->findIncidence( r->id() );
+ if ( !e )
+ {
+ // no corresponding entry found, so create, copy and insert it.
+ e = newIncidence();
+ incidenceFromRecord( e, de );
+ fP->addIncidence( e );
+ fCtrPC->created();
+ }
+ else
+ {
+ // similar entry found, so just copy, no need to insert again
+ incidenceFromRecord( e, de );
+ fCtrPC->updated();
+ }
+ }
+ KPILOT_DELETE( de );
+ return e;
+}
+
+int VCalConduitBase::resolveConflict( KCal::Incidence *e, PilotRecordBase *de ) {
+ if ( getConflictResolution() == SyncAction::eAskUser )
+ {
+ // TODO: This is messed up!!!
+ QString query = i18n( "The following item was modified "
+ "both on the Handheld and on your PC:\nPC entry:\n\t" );
+ query += e->summary();
+ query += i18n( "\nHandheld entry:\n\t" );
+ query += getTitle( de );
+ query += i18n( "\n\nWhich entry do you want to keep? It will "
+ "overwrite the other entry." );
+
+ return KMessageBox::No == questionYesNo(
+ query,
+ i18n( "Conflicting Entries" ),
+ QString::null,
+ 0 /* Never timeout */,
+ i18n( "Handheld" ), i18n( "PC" ));
+ }
+ return getConflictResolution();
+}
+
+KCal::Incidence*VCalConduitBase::changeRecord(PilotRecord *r,PilotRecord *)
+{
+ FUNCTIONSETUP;
+
+ PilotRecordBase *de = newPilotEntry( r );
+ KCal::Incidence *e = fP->findIncidence( r->id() );
+
+ DEBUGKPILOT << fname << ": Pilot Record ID: [" << r->id() << "]" << endl;
+
+ if ( e && de )
+ {
+ // TODO: check for conflict, and if there is one, ask for resolution
+ if ( ( e->syncStatus() != KCal::Incidence::SYNCNONE )
+ && r->isModified() )
+ {
+ // TODO: I have not yet found a way to complete ignore an item
+ if (resolveConflict( e, de ) )
+ {
+ // PC record takes precedence:
+ KPILOT_DELETE( de );
+ return e;
+ }
+ }
+ // no conflict or conflict resolution says, Palm overwrites, so do it:
+ incidenceFromRecord( e, de );
+
+ // NOTE: This MUST be done last, since every other set* call
+ // calls updated(), which will trigger an
+ // setSyncStatus(SYNCMOD)!!!
+ e->setSyncStatus(KCal::Incidence::SYNCNONE);
+ fLocalDatabase->writeRecord( r );
+ }
+ else
+ {
+ WARNINGKPILOT
+ << "While changing record -- not found in iCalendar" << endl;
+ addRecord( r );
+ }
+
+ KPILOT_DELETE( de );
+ return e;
+}
+
+
+KCal::Incidence*VCalConduitBase::deleteRecord( PilotRecord *r, PilotRecord * )
+{
+ FUNCTIONSETUP;
+
+ KCal::Incidence *e = fP->findIncidence(r->id());
+ if (e)
+ {
+ // RemoveEvent also takes it out of the calendar.
+ fP->removeIncidence(e);
+ fCtrPC->deleted();
+ }
+ fLocalDatabase->writeRecord( r );
+ return NULL;
+}
+
+
+void VCalConduitBase::addPalmRecord( KCal::Incidence *e )
+{
+ FUNCTIONSETUP;
+
+ PilotRecordBase *de = newPilotEntry( 0L );
+ updateIncidenceOnPalm( e, de );
+ fCtrHH->created();
+ KPILOT_DELETE( de );
+}
+
+
+void VCalConduitBase::changePalmRecord(KCal::Incidence*e, PilotRecord*s)
+{
+ PilotRecordBase *de = newPilotEntry( s );
+ updateIncidenceOnPalm( e, de );
+ fCtrHH->updated();
+ KPILOT_DELETE( de );
+}
+
+
+void VCalConduitBase::deletePalmRecord( KCal::Incidence *e, PilotRecord *s )
+{
+ FUNCTIONSETUP;
+ if ( s )
+ {
+ DEBUGKPILOT << fname << ": deleting record " << s->id() << endl;
+ s->setDeleted();
+ fDatabase->writeRecord( s );
+ fLocalDatabase->writeRecord( s );
+ fCtrHH->deleted();
+ }
+ else
+ {
+ DEBUGKPILOT << fname << ": could not find record to delete (";
+ DEBUGKPILOT << e->pilotId() << ")" << endl;
+ }
+
+ Q_UNUSED(e);
+}
+
+/* I have to use a pointer to an existing PilotDateEntry so that I can handle
+ new records as well (and to prevent some crashes concerning the validity
+ domain of the PilotRecord*r). In syncEvent this PilotDateEntry is created. */
+void VCalConduitBase::updateIncidenceOnPalm( KCal::Incidence *e,
+ PilotRecordBase *de )
+{
+ FUNCTIONSETUP;
+ if ( !de || !e ) {
+ DEBUGKPILOT << fname << ": NULL event given... Skipping it" << endl;
+ return;
+ }
+
+ if ( e->syncStatus() == KCal::Incidence::SYNCDEL )
+ {
+ DEBUGKPILOT << fname << ": don't write deleted incidence "
+ << e->summary() << " to the palm" << endl;
+ return;
+ }
+
+ PilotRecord *r = recordFromIncidence( de, e );
+
+ // TODO: Check for conflict!
+ if ( r )
+ {
+ recordid_t id=fDatabase->writeRecord(r);
+ r->setID(id);
+// r->setAttrib(r->getAttrib() & ~dlpRecAttrDeleted);
+ fLocalDatabase->writeRecord( r );
+// fDatabase->writeRecord(r);
+ e->setPilotId( id );
+
+ // NOTE: This MUST be done last, since every other set* call
+ // calls updated(), which will trigger an
+ // setSyncStatus(SYNCMOD)!!!
+ e->setSyncStatus(KCal::Incidence::SYNCNONE);
+ KPILOT_DELETE( r );
+ }
+}
+
+const QString VCalConduitBase::dbname()
+{
+ return QString::null;
+}
+
+PilotRecord *VCalConduitBase::readRecordByIndex( int index )
+{
+ FUNCTIONSETUP;
+ return fDatabase->readRecordByIndex( index );
+}
+
+KCal::Incidence *VCalConduitBase::incidenceFromRecord( PilotRecord *r )
+{
+ FUNCTIONSETUP;
+ PilotRecordBase *pac = newPilotEntry( r );
+ KCal::Incidence *i = newIncidence();
+ incidenceFromRecord( i, pac );
+
+ KPILOT_DELETE( pac );
+ return i;
+}
+
+void VCalConduitBase::setState( ConduitState *s )
+{
+ KPILOT_DELETE( fState );
+ fState = s;
+}
+
+/* virtual */ void VCalConduitBase::postSync( )
+{
+ FUNCTIONSETUP;
+ if (fCtrPC && fP)
+ fCtrPC->setEndCount(fP->count());
+}
+
+/* virtual */ void VCalConduitBase::preSync( )
+{
+ FUNCTIONSETUP;
+ if (fCtrPC && fP)
+ fCtrPC->setStartCount(fP->count());
+}
diff --git a/kpilot/conduits/vcalconduit/vcal-conduitbase.h b/kpilot/conduits/vcalconduit/vcal-conduitbase.h
new file mode 100644
index 000000000..7d2fc6588
--- /dev/null
+++ b/kpilot/conduits/vcalconduit/vcal-conduitbase.h
@@ -0,0 +1,202 @@
+#ifndef _KPILOT_VCAL_CONDUITBASE_H
+#define _KPILOT_VCAL_CONDUITBASE_H
+/* vcal-conduit.h KPilot
+**
+** Copyright (C) 2002-2003 Reinhold Kainhofer
+** Copyright (C) 2001 by Dan Pilone
+**
+** This file defines the vcal-conduit plugin.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+
+#include <qstring.h>
+
+#include <libkcal/calendarlocal.h>
+
+#include <plugin.h>
+#include <pilotRecord.h>
+
+namespace KCal
+{
+class Calendar;
+class Incidence;
+}
+
+class PilotSerialDatabase;
+class PilotLocalDatabase;
+class VCalConduitSettings;
+
+class ConduitState;
+
+class VCalConduitPrivateBase
+{
+protected:
+ bool reading;
+ KCal::Calendar *fCalendar;
+public:
+ VCalConduitPrivateBase(KCal::Calendar *buddy) : fCalendar(buddy)
+ {
+ reading = false;
+ };
+
+ virtual ~VCalConduitPrivateBase() { } ;
+
+ virtual int updateIncidences() = 0;
+ virtual void addIncidence(KCal::Incidence*) = 0;
+ virtual void removeIncidence(KCal::Incidence*) = 0;
+ virtual KCal::Incidence *findIncidence(recordid_t) = 0;
+ virtual KCal::Incidence *findIncidence(PilotRecordBase *tosearch) = 0;
+ virtual KCal::Incidence *getNextIncidence() = 0;
+ virtual KCal::Incidence *getNextModifiedIncidence() = 0;
+ virtual int count()=0;
+} ;
+
+class VCalConduitBase : public ConduitAction
+{
+ Q_OBJECT
+public:
+ VCalConduitBase(KPilotLink *,
+ const char *name = 0L,
+ const QStringList &args = QStringList());
+ virtual ~VCalConduitBase();
+
+/*********************************************************************
+ D A T A M E M B E R S , S E T T I N G S
+ *********************************************************************/
+protected:
+ KCal::Calendar *fCalendar;
+ QString fCalendarFile;
+ VCalConduitPrivateBase *fP;
+ ConduitState *fState;
+ bool hasNextRecord;
+
+ virtual const QString dbname() = 0;
+ virtual const QString getTitle(PilotRecordBase *de) = 0;
+ virtual void readConfig();
+
+ virtual bool exec();
+
+protected slots:
+ /**
+ * This slot is used to execute the actions applicable to this conduit. What
+ * happens in this method is defined by the state the conduit has at the
+ * moment that this method is called. For more information about the actions
+ * that are executed, look at the classes that are implementing ConduitState.
+ */
+ void slotProcess();
+
+public:
+ /**
+ * Method used by state classes to indicatie if there are more records to
+ * deal with.
+ */
+ void setHasNextRecord( bool b )
+ {
+ hasNextRecord = b;
+ }
+
+ /**
+ * Change the current state of the conduit. The state that the conduit has
+ * at the moment of the call will be deleted. The last state *must* set the
+ * state to 0L when finished.
+ */
+ void setState( ConduitState *s );
+
+ /**
+ * Returns the privatebase, that is used to for accessing the local calendar.
+ */
+ VCalConduitPrivateBase *privateBase() const
+ {
+ return fP;
+ }
+
+ /**
+ * Returns the record at index from the palm or 0L if there is no record at
+ * index.
+ */
+ PilotRecord *readRecordByIndex( int index );
+
+ /**
+ * Returns a KCal::Incidence constructed from PilotRecord r. If r is 0L the
+ * it will return a KCal::Incidence that is empty.
+ */
+ KCal::Incidence *incidenceFromRecord( PilotRecord *r );
+
+ virtual void preIncidence( KCal::Incidence* ) {};
+
+ // Getters
+ KCal::Calendar *calendar() const { return fCalendar; };
+ QString calendarFile() const { return fCalendarFile; };
+
+ virtual VCalConduitSettings *config() = 0;
+ virtual PilotDatabase *database() const { return fDatabase; };
+ virtual PilotDatabase *localDatabase() const { return fLocalDatabase; };
+
+ // add, change or delete records from the palm
+ virtual void addPalmRecord( KCal::Incidence *e );
+ virtual void changePalmRecord( KCal::Incidence *e, PilotRecord *s );
+ virtual void deletePalmRecord( KCal::Incidence *e, PilotRecord *s );
+
+ // add, change or delete events from the calendar
+ virtual KCal::Incidence* changeRecord( PilotRecord*, PilotRecord* );
+ virtual KCal::Incidence* deleteRecord( PilotRecord*, PilotRecord* );
+ virtual KCal::Incidence* addRecord( PilotRecord * );
+
+/*********************************************************************
+ P R E - A N D P O S T S Y N C F U N C T I O N S
+ *********************************************************************/
+ virtual void preSync();
+ virtual void postSync();
+ virtual void preRecord(PilotRecord*) {};
+
+protected:
+ virtual void updateIncidenceOnPalm(KCal::Incidence *e, PilotRecordBase *de);
+
+/*********************************************************************
+ S Y N C F U N C T I O N S
+ for creating events from Palm records or vice versa
+ *********************************************************************/
+ virtual PilotRecord *recordFromIncidence(PilotRecordBase *de,
+ const KCal::Incidence *e) = 0;
+ virtual PilotRecordBase *newPilotEntry(PilotRecord *r) = 0;
+
+ virtual KCal::Incidence *newIncidence() = 0;
+ virtual KCal::Incidence *incidenceFromRecord(KCal::Incidence *e,
+ const PilotRecordBase *de) = 0;
+
+/*********************************************************************
+ M I S C F U N C T I O N S
+ *********************************************************************/
+ /**
+ * Return how to resolve conflicts. For now
+ * PalmOverrides=0=false,
+ * PCOverrides=1=true,
+ * Ask=2-> ask the user using a messagebox
+ */
+ virtual int resolveConflict(KCal::Incidence *e, PilotRecordBase *de);
+ virtual bool openCalendar();
+ virtual VCalConduitPrivateBase *createPrivateCalendarData(KCal::Calendar *fCalendar) = 0;
+} ;
+
+#endif
diff --git a/kpilot/conduits/vcalconduit/vcal-factory.cc b/kpilot/conduits/vcalconduit/vcal-factory.cc
new file mode 100644
index 000000000..2e157818f
--- /dev/null
+++ b/kpilot/conduits/vcalconduit/vcal-factory.cc
@@ -0,0 +1,50 @@
+/* KPilot
+**
+** Copyright (C) 2002-2003 Reinhold Kainhofer
+** Copyright (C) 2001 by Dan Pilone
+**
+** This file defines the factory for the vcal-conduit plugin.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include "options.h"
+
+#include <kaboutdata.h>
+
+#include "pluginfactory.h"
+
+#include "vcal-setup.h"
+#include "vcal-conduit.h"
+
+extern "C"
+{
+
+void *init_conduit_vcal()
+{
+ return new ConduitFactory<VCalWidgetSetup,VCalConduit>;
+}
+
+}
+
+
+
diff --git a/kpilot/conduits/vcalconduit/vcal-factory.h b/kpilot/conduits/vcalconduit/vcal-factory.h
new file mode 100644
index 000000000..5cd4a611b
--- /dev/null
+++ b/kpilot/conduits/vcalconduit/vcal-factory.h
@@ -0,0 +1,41 @@
+#ifndef _KPILOT_VCAL_FACTORY_H
+#define _KPILOT_VCAL_FACTORY_H
+/* vcal-factory.h KPilot
+**
+** Copyright (C) 2002-2003 Reinhold Kainhofer
+** Copyright (C) 2001 by Dan Pilone
+**
+** This file defines the factory for the vcal-conduit plugin.
+** It also defines the class for the behavior of the setup dialog.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+
+extern "C"
+{
+
+void *init_libvcalconduit();
+
+}
+
+#endif
diff --git a/kpilot/conduits/vcalconduit/vcal-factorybase.h b/kpilot/conduits/vcalconduit/vcal-factorybase.h
new file mode 100644
index 000000000..5a1d2a5d6
--- /dev/null
+++ b/kpilot/conduits/vcalconduit/vcal-factorybase.h
@@ -0,0 +1,44 @@
+#ifndef _KPILOT_VCAL_FACTORYBASE_H
+#define _KPILOT_VCAL_FACTORYBASE_H
+/* vcal-factory.h KPilot
+**
+** Copyright (C) 2002-2003 Reinhold Kainhofer
+** Copyright (C) 2001 by Dan Pilone
+**
+** This file defines the factory for the vcal-conduit plugin.
+** It also defines the class for the behavior of the setup dialog.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+
+#define RES_PALMOVERRIDES 0
+#define RES_PCOVERRIDES 1
+#define RES_ASK 2
+
+#define SYNC_FIRST 0
+#define SYNC_FAST 1
+#define SYNC_FULL 2
+#define SYNC_MAX SYNC_FULL
+
+
+#endif
diff --git a/kpilot/conduits/vcalconduit/vcal-setup.cc b/kpilot/conduits/vcalconduit/vcal-setup.cc
new file mode 100644
index 000000000..666e9ee0a
--- /dev/null
+++ b/kpilot/conduits/vcalconduit/vcal-setup.cc
@@ -0,0 +1,78 @@
+/* KPilot
+**
+** Copyright (C) 2002-2003 Reinhold Kainhofer
+** Copyright (C) 2001 by Dan Pilone
+**
+** This file defines the setup dialog for the vcal-conduit plugin.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include "options.h"
+
+#include <qbuttongroup.h>
+#include <kaboutdata.h>
+
+#include "korganizerConduit.h"
+#include "vcal-conduit.h"
+#include "vcal-setup.h"
+
+
+VCalWidgetSetup::VCalWidgetSetup(QWidget *w, const char *n) :
+ VCalWidgetSetupBase(w,n)
+{
+ KAboutData *fAbout = new KAboutData("vcalConduit",
+ I18N_NOOP("VCal Conduit for KPilot"),
+ KPILOT_VERSION,
+ I18N_NOOP("Configures the VCal Conduit for KPilot"),
+ KAboutData::License_GPL,
+ "(C) 2001, Adriaan de Groot\n(C) 2002-2003, Reinhold Kainhofer");
+ fAbout->addAuthor("Adriaan de Groot",
+ I18N_NOOP("Maintainer"),
+ "groot@kde.org",
+ "http://www.kpilot.org/");
+ fAbout->addAuthor("Reinhold Kainhofer",
+ I18N_NOOP("Maintainer"),
+ "reinhold@kainhofer.com",
+ "http://reinhold.kainhofer.com/Linux/");
+ fAbout->addAuthor("Dan Pilone",
+ I18N_NOOP("Original Author"));
+ fAbout->addAuthor("Preston Brown",
+ I18N_NOOP("Original Author"));
+ fAbout->addAuthor("Herwin-Jan Steehouwer",
+ I18N_NOOP("Original Author"));
+ fAbout->addCredit("Cornelius Schumacher",
+ I18N_NOOP("iCalendar port"));
+ fAbout->addCredit("Philipp Hullmann",
+ I18N_NOOP("Bugfixer"));
+
+ ConduitConfigBase::addAboutPage(fConfigWidget->tabWidget, fAbout);
+ fConfigWidget->fSyncDestination->setTitle(i18n("Calendar Destination"));
+ fConduitName=i18n("Calendar");
+
+}
+
+/* static */ ConduitConfigBase *VCalWidgetSetup::create(QWidget *w,const char *n)
+{
+ return new VCalWidgetSetup(w,n);
+}
+VCalConduitSettings*VCalWidgetSetup::config() { return VCalConduit::theConfig(); }
diff --git a/kpilot/conduits/vcalconduit/vcal-setup.h b/kpilot/conduits/vcalconduit/vcal-setup.h
new file mode 100644
index 000000000..407c0d99f
--- /dev/null
+++ b/kpilot/conduits/vcalconduit/vcal-setup.h
@@ -0,0 +1,46 @@
+#ifndef _KPILOT_VCAL_SETUP_H
+#define _KPILOT_VCAL_SETUP_H
+/* vcal-setup.h KPilot
+**
+** Copyright (C) 2002-2003 Reinhold Kainhofer
+** Copyright (C) 2001 by Dan Pilone
+**
+** It also defines the class for the behavior of the setup dialog.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include "vcal-setupbase.h"
+
+class VCalWidget;
+class VCalConduitSettings;
+
+class VCalWidgetSetup : public VCalWidgetSetupBase
+{
+public:
+ VCalWidgetSetup(QWidget *, const char *);
+ static ConduitConfigBase *create(QWidget *, const char *);
+protected:
+ virtual VCalConduitSettings*config();
+} ;
+
+#endif
diff --git a/kpilot/conduits/vcalconduit/vcal-setupbase.cc b/kpilot/conduits/vcalconduit/vcal-setupbase.cc
new file mode 100644
index 000000000..3e97987fa
--- /dev/null
+++ b/kpilot/conduits/vcalconduit/vcal-setupbase.cc
@@ -0,0 +1,110 @@
+/* vcal-setup.cc KPilot
+**
+** Copyright (C) 2002-2003 Reinhold Kainhofer
+** Copyright (C) 2001 by Dan Pilone
+**
+** This file defines the setup dialog for the vcal-conduit plugin.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include "options.h"
+
+#include <qcheckbox.h>
+#include <qbuttongroup.h>
+#include <qcombobox.h>
+
+#include <kurlrequester.h>
+
+#include "korganizerConduit.h"
+#include "vcalconduitSettings.h"
+#include "vcal-setupbase.h"
+
+VCalWidgetSetupBase::VCalWidgetSetupBase(QWidget *w, const char *n) :
+ ConduitConfigBase(w,n),
+ fConfigWidget(new VCalWidget(w))
+{
+ FUNCTIONSETUP;
+ fWidget=fConfigWidget;
+
+ fConfigWidget->fCalendarFile->setMode(KFile::File);
+ fConfigWidget->fCalendarFile->setFilter(CSL1("*.vcs *.ics|ICalendars\n*.*|All Files (*.*)"));
+
+#define CM(a,b) connect(fConfigWidget->a,b,this,SLOT(modified()));
+ CM(fSyncDestination,SIGNAL(clicked(int)));
+ CM(fCalendarFile,SIGNAL(textChanged(const QString &)));
+ CM(fArchive,SIGNAL(toggled(bool)));
+ CM(fConflictResolution,SIGNAL(activated(int)));
+#undef CM
+}
+
+VCalWidgetSetupBase::~VCalWidgetSetupBase()
+{
+ FUNCTIONSETUP;
+}
+
+/* virtual */ void VCalWidgetSetupBase::commit()
+{
+ FUNCTIONSETUP;
+ config()->readConfig();
+
+ // General page
+#ifdef DEBUG
+ DEBUGKPILOT << fname << ": Selected type="
+ << fConfigWidget->fSyncDestination->selected()
+ << " with id="
+ << fConfigWidget->fSyncDestination->id(fConfigWidget->fSyncDestination->selected())
+ << endl;
+#endif
+ config()->setCalendarType( fConfigWidget->fSyncDestination->id(
+ fConfigWidget->fSyncDestination->selected()));
+ config()->setCalendarFile( fConfigWidget->fCalendarFile->url());
+
+ config()->setSyncArchived( fConfigWidget->fArchive->isChecked() );
+
+ // Conflicts page
+ config()->setConflictResolution(
+ fConfigWidget->fConflictResolution->currentItem()+SyncAction::eCROffset);
+
+ config()->writeConfig();
+ unmodified();
+}
+
+/* virtual */ void VCalWidgetSetupBase::load()
+{
+ FUNCTIONSETUP;
+ config()->readConfig();
+
+ // General page
+ fConfigWidget->fSyncDestination->setButton( config()->calendarType());
+ fConfigWidget->fCalendarFile->setURL( config()->calendarFile() );
+
+ fConfigWidget->fArchive->setChecked( config()->syncArchived() );
+
+ // Conflicts page
+ fConfigWidget->fConflictResolution->setCurrentItem(
+ config()->conflictResolution() - SyncAction::eCROffset);
+
+ config()->writeConfig();
+ unmodified();
+}
+
diff --git a/kpilot/conduits/vcalconduit/vcal-setupbase.h b/kpilot/conduits/vcalconduit/vcal-setupbase.h
new file mode 100644
index 000000000..7863659bd
--- /dev/null
+++ b/kpilot/conduits/vcalconduit/vcal-setupbase.h
@@ -0,0 +1,51 @@
+#ifndef _KPILOT_VCAL_SETUPBASE_H
+#define _KPILOT_VCAL_SETUPBASE_H
+/* vcal-setup.h KPilot
+**
+** Copyright (C) 2002-2003 Reinhold Kainhofer
+** Copyright (C) 2001 by Dan Pilone
+**
+** It also defines the class for the behavior of the setup dialog.
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include "plugin.h"
+
+class VCalWidget;
+class VCalConduitSettings;
+
+class VCalWidgetSetupBase : public ConduitConfigBase
+{
+public:
+ VCalWidgetSetupBase(QWidget *, const char *);
+ virtual ~VCalWidgetSetupBase();
+
+ virtual void load();
+ virtual void commit();
+
+protected:
+ virtual VCalConduitSettings*config()=0;
+ VCalWidget *fConfigWidget;
+} ;
+
+#endif
diff --git a/kpilot/conduits/vcalconduit/vcalRecord.cc b/kpilot/conduits/vcalconduit/vcalRecord.cc
new file mode 100644
index 000000000..f9866d91a
--- /dev/null
+++ b/kpilot/conduits/vcalconduit/vcalRecord.cc
@@ -0,0 +1,548 @@
+/* vcalRecord.cc KPilot
+**
+** Copyright (C) 2006 by Adriaan de Groot <groot@kde.org>
+** Copyright (C) 2002-2003 by Reinhold Kainhofer
+** Copyright (C) 2001 by Dan Pilone
+**
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include "options.h"
+
+#include <libkcal/calendar.h>
+#include <libkcal/calendarlocal.h>
+#include <libkcal/recurrence.h>
+#include <libkcal/vcalformat.h>
+
+#include "pilot.h"
+#include "pilotDateEntry.h"
+
+#include "kcalRecord.h"
+#include "vcalRecord.h"
+
+
+static void setStartEndTimes(KCal::Event *e, const PilotDateEntry *de)
+{
+ FUNCTIONSETUP;
+ DEBUGKPILOT << fname
+ << "# Start time on Palm: "
+ << readTm(de->getEventStart()).toString() << endl;
+
+ e->setDtStart(readTm(de->getEventStart()));
+ e->setFloats(de->isEvent());
+
+ if (de->isMultiDay())
+ {
+ e->setDtEnd(readTm(de->getRepeatEnd()));
+ }
+ else
+ {
+ e->setDtEnd(readTm(de->getEventEnd()));
+ }
+}
+
+static void setAlarms(KCal::Event *e, const PilotDateEntry *de)
+{
+ FUNCTIONSETUP;
+
+ if (!e) return;
+ // Delete all the alarms now and add them one by one later on.
+ e->clearAlarms();
+ if (!de->isAlarmEnabled()) return;
+
+// QDateTime alarmDT = readTm(de->getEventStart());
+ int advanceUnits = de->getAdvanceUnits();
+
+ switch (advanceUnits)
+ {
+ case advMinutes:
+ advanceUnits = 1;
+ break;
+ case advHours:
+ advanceUnits = 60;
+ break;
+ case advDays:
+ advanceUnits = 60*24;
+ break;
+ default:
+#ifdef DEBUG
+ DEBUGKPILOT << fname
+ << ": Unknown advance units "
+ << advanceUnits
+ << endl;
+#endif
+ advanceUnits=1;
+ }
+
+ KCal::Duration adv(-60*advanceUnits*de->getAdvance());
+ KCal::Alarm*alm=e->newAlarm();
+ if (!alm) return;
+
+ alm->setStartOffset(adv);
+ alm->setEnabled(true);
+}
+
+static void setRecurrence(KCal::Event *event,const PilotDateEntry *dateEntry)
+{
+ FUNCTIONSETUP;
+
+ if ((dateEntry->getRepeatType() == repeatNone) || dateEntry->isMultiDay())
+ {
+#ifdef DEBUG
+ DEBUGKPILOT<<fname<<": no recurrence to set"<<endl;
+#endif
+ return;
+ }
+
+ KCal::Recurrence *recur = event->recurrence();
+ int freq = dateEntry->getRepeatFrequency();
+ bool repeatsForever = dateEntry->getRepeatForever();
+ QDate endDate, evt;
+
+ if (!repeatsForever)
+ {
+ endDate = readTm(dateEntry->getRepeatEnd()).date();
+#ifdef DEBUG
+ DEBUGKPILOT << fname << "-- end " << endDate.toString() << endl;
+ }
+ else
+ {
+ DEBUGKPILOT << fname << "-- noend" << endl;
+#endif
+ }
+
+ QBitArray dayArray(7);
+
+ switch(dateEntry->getRepeatType())
+ {
+ case repeatDaily:
+ recur->setDaily(freq);
+ break;
+ case repeatWeekly:
+ {
+ const int *days = dateEntry->getRepeatDays();
+
+#ifdef DEBUG
+ DEBUGKPILOT << fname
+ << ": Got repeat-weekly entry, by-days="
+ << days[0] << " "<< days[1] << " "<< days[2] << " "
+ << days[3] << " "
+ << days[4] << " "<< days[5] << " "<< days[6] << " "
+ << endl;
+#endif
+
+ // Rotate the days of the week, since day numbers on the Pilot and
+ // in vCal / Events are different.
+ //
+ if (days[0]) dayArray.setBit(6);
+ for (int i = 1; i < 7; i++)
+ {
+ if (days[i]) dayArray.setBit(i-1);
+ }
+ recur->setWeekly( freq, dayArray );
+ }
+ break;
+ case repeatMonthlyByDay: {
+ // Palm: Day=0(sun)-6(sat); week=0-4, 4=last week; pos=week*7+day
+ // libkcal: day=bit0(mon)-bit6(sun); week=-5to-1(from end) and 1-5 (from beginning)
+ // Palm->PC: w=pos/7
+ // week: if w=4 -> week=-1, else week=w+1;
+ // day: day=(pos-1)%7 (rotate by one day!)
+ recur->setMonthly( freq );
+
+ int day=dateEntry->getRepeatDay();
+ int week=day/7;
+ // week=4 means last, otherwise convert to 0-based
+ if (week==4) week=-1; else week++;
+ dayArray.setBit((day+6) % 7);
+ recur->addMonthlyPos(week, dayArray);
+ break;}
+ case repeatMonthlyByDate:
+ recur->setMonthly( freq );
+ recur->addMonthlyDate( dateEntry->getEventStart().tm_mday );
+ break;
+ case repeatYearly:
+ recur->setYearly( freq );
+ evt=readTm(dateEntry->getEventStart()).date();
+ recur->addYearlyMonth( evt.month() );
+// dayArray.setBit((evt.day()-1) % 7);
+// recur->addYearlyMonthPos( ( (evt.day()-1) / 7) + 1, dayArray );
+ break;
+ case repeatNone:
+ default :
+#ifdef DEBUG
+ DEBUGKPILOT << fname
+ << ": Can't handle repeat type "
+ << dateEntry->getRepeatType()
+ << endl;
+#endif
+ break;
+ }
+ if (!repeatsForever)
+ {
+ recur->setEndDate(endDate);
+ }
+}
+
+static void setExceptions(KCal::Event *vevent,const PilotDateEntry *dateEntry)
+{
+ FUNCTIONSETUP;
+
+ // Start from an empty exception list, and if necessary, add exceptions.
+ // At the end of the function, apply the (possibly empty) exception list.
+ KCal::DateList dl;
+
+ if ( !(dateEntry->isMultiDay() ) && dateEntry->getExceptionCount()>0 )
+ {
+ for (int i = 0; i < dateEntry->getExceptionCount(); i++)
+ {
+// vevent->addExDate(readTm(dateEntry->getExceptions()[i]).date());
+ dl.append(readTm(dateEntry->getExceptions()[i]).date());
+ }
+ }
+ else
+ {
+#ifdef DEBUG
+ if (dateEntry->getExceptionCount()>0)
+ DEBUGKPILOT << fname
+ << ": WARNING Exceptions ignored for multi-day event "
+ << dateEntry->getDescription()
+ << endl ;
+#endif
+ return;
+ }
+ vevent->recurrence()->setExDates(dl);
+}
+
+static void setStartEndTimes(PilotDateEntry*de, const KCal::Event *e)
+{
+ FUNCTIONSETUP;
+ struct tm ttm=writeTm(e->dtStart());
+ de->setEventStart(ttm);
+ de->setFloats( e->doesFloat() );
+
+ if (e->hasEndDate() && e->dtEnd().isValid())
+ {
+ ttm=writeTm(e->dtEnd());
+ }
+ else
+ {
+ ttm=writeTm(e->dtStart());
+ }
+ de->setEventEnd(ttm);
+}
+
+
+
+
+static void setAlarms(PilotDateEntry*de, const KCal::Event *e)
+{
+ FUNCTIONSETUP;
+
+ if (!de || !e )
+ {
+#ifdef DEBUG
+ DEBUGKPILOT << fname << ": NULL entry given to setAlarms. "<<endl;
+#endif
+ return;
+ }
+
+ if ( !e->isAlarmEnabled() )
+ {
+ de->setAlarmEnabled( false );
+ return;
+ }
+
+ // find the first enabled alarm
+ KCal::Alarm::List alms=e->alarms();
+ KCal::Alarm* alm=0;
+ KCal::Alarm::List::ConstIterator it;
+ for ( it = alms.begin(); it != alms.end(); ++it ) {
+ if ((*it)->enabled()) alm=*it;
+ }
+
+ if (!alm )
+ {
+#ifdef DEBUG
+ DEBUGKPILOT << fname << ": no enabled alarm found (should exist!!!)"<<endl;
+#endif
+ de->setAlarmEnabled( false );
+ return;
+ }
+
+ // palm and PC offsets have a different sign!!
+ int aoffs=-alm->startOffset().asSeconds()/60;
+ int offs=(aoffs>0)?aoffs:-aoffs;
+
+ // find the best Advance Unit
+ if (offs>=100 || offs==60)
+ {
+ offs/=60;
+ if (offs>=48 || offs==24)
+ {
+ offs/=24;
+ de->setAdvanceUnits(advDays);
+ }
+ else
+ {
+ de->setAdvanceUnits(advHours);
+ }
+ }
+ else
+ {
+ de->setAdvanceUnits(advMinutes);
+ }
+ de->setAdvance((aoffs>0)?offs:-offs);
+ de->setAlarmEnabled( true );
+}
+
+
+
+static void setRecurrence(PilotDateEntry*dateEntry, const KCal::Event *event)
+{
+ FUNCTIONSETUP;
+ bool isMultiDay=false;
+
+ // first we have 'fake type of recurrence' when a multi-day event is passed to the pilot, it is converted to an event
+ // which recurs daily a number of times. if the event itself recurs, this will be overridden, and
+ // only the first day will be included in the event!!!!
+ QDateTime startDt(readTm(dateEntry->getEventStart())), endDt(readTm(dateEntry->getEventEnd()));
+ if (startDt.daysTo(endDt))
+ {
+ isMultiDay=true;
+ dateEntry->setRepeatType(repeatDaily);
+ dateEntry->setRepeatFrequency(1);
+ dateEntry->setRepeatEnd(dateEntry->getEventEnd());
+#ifdef DEBUG
+ DEBUGKPILOT << fname <<": Setting single-day recurrence (" << startDt.toString() << " - " << endDt.toString() << ")" <<endl;
+#endif
+ }
+
+
+ KCal::Recurrence*r=event->recurrence();
+ if (!r) return;
+ ushort recType=r->recurrenceType();
+ if ( recType==KCal::Recurrence::rNone )
+ {
+ if (!isMultiDay) dateEntry->setRepeatType(repeatNone);
+ return;
+ }
+
+
+ int freq=r->frequency();
+ QDate endDate=r->endDate();
+
+ if ( r->duration() < 0 || !endDate.isValid() )
+ {
+ dateEntry->setRepeatForever();
+ }
+ else
+ {
+ dateEntry->setRepeatEnd(writeTm(endDate));
+ }
+ dateEntry->setRepeatFrequency(freq);
+#ifdef DEBUG
+ DEBUGKPILOT<<" Event: "<<event->summary()<<" ("<<event->description()<<")"<<endl;
+ DEBUGKPILOT<< "duration: "<<r->duration() << ", endDate: "<<endDate.toString()<< ", ValidEndDate: "<<endDate.isValid()<<", NullEndDate: "<<endDate.isNull()<<endl;
+#endif
+
+ QBitArray dayArray(7), dayArrayPalm(7);
+ switch(recType)
+ {
+ case KCal::Recurrence::rDaily:
+ dateEntry->setRepeatType(repeatDaily);
+ break;
+ case KCal::Recurrence::rWeekly:
+ dateEntry->setRepeatType(repeatWeekly);
+ dayArray=r->days();
+ // rotate the bits by one
+ for (int i=0; i<7; i++)
+ {
+ dayArrayPalm.setBit( (i+1)%7, dayArray[i]);
+ }
+ dateEntry->setRepeatDays(dayArrayPalm);
+ break;
+ case KCal::Recurrence::rMonthlyPos:
+ // Palm: Day=0(sun)-6(sat); week=0-4, 4=last week; pos=week*7+day
+ // libkcal: day=bit0(mon)-bit6(sun); week=-5to-1(from end) and 1-5 (from beginning)
+ // PC->Palm: pos=week*7+day
+ // week: if w=-1 -> week=4, else week=w-1
+ // day: day=(daybit+1)%7 (rotate because of the different offset)
+ dateEntry->setRepeatType(repeatMonthlyByDay);
+ if (r->monthPositions().count()>0)
+ {
+ // Only take the first monthly position, as the palm allows only one
+ QValueList<KCal::RecurrenceRule::WDayPos> mps=r->monthPositions();
+ KCal::RecurrenceRule::WDayPos mp=mps.first();
+ int week = mp.pos();
+ int day = (mp.day()+1) % 7; // rotate because of different offset
+ // turn to 0-based and include starting from end of month
+ // TODO: We don't handle counting from the end of the month yet!
+ if (week==-1) week=4; else week--;
+ dateEntry->setRepeatDay(static_cast<DayOfMonthType>(7*week + day));
+ }
+ break;
+ case KCal::Recurrence::rMonthlyDay:
+ dateEntry->setRepeatType(repeatMonthlyByDate);
+//TODO: is this needed? dateEntry->setRepeatDay(static_cast<DayOfMonthType>(startDt.day()));
+ break;
+ case KCal::Recurrence::rYearlyDay:
+ case KCal::Recurrence::rYearlyPos:
+ DEBUGKPILOT << fname
+ << "! Unsupported yearly recurrence type." << endl;
+ case KCal::Recurrence::rYearlyMonth:
+ dateEntry->setRepeatType(repeatYearly);
+ break;
+ case KCal::Recurrence::rNone:
+ if (!isMultiDay) dateEntry->setRepeatType(repeatNone);
+ break;
+ default:
+#ifdef DEBUG
+ DEBUGKPILOT << fname << ": Unknown recurrence type "<< recType << " with frequency "
+ << freq << " and duration " << r->duration() << endl;
+#endif
+ break;
+ }
+}
+
+
+static void setExceptions(PilotDateEntry *dateEntry, const KCal::Event *vevent )
+{
+ FUNCTIONSETUP;
+ struct tm *ex_List;
+
+ if (!dateEntry || !vevent)
+ {
+ WARNINGKPILOT << "NULL dateEntry or NULL vevent given for exceptions. Skipping exceptions" << endl;
+ return;
+ }
+ // first, we need to delete the old exceptions list, if it existed...
+ // This is no longer needed, as I fixed PilotDateEntry::setExceptions to do this automatically
+/* ex_List=const_cast<structdateEntry->getExceptions();
+ if (ex_List)
+ KPILOT_DELETE(ex_List);*/
+
+ KCal::DateList exDates = vevent->recurrence()->exDates();
+ size_t excount = exDates.size();
+ if (excount<1)
+ {
+ dateEntry->setExceptionCount(0);
+ dateEntry->setExceptions(0);
+ return;
+ }
+
+ // we have exceptions, so allocate mem and copy them there...
+ ex_List=new struct tm[excount];
+ if (!ex_List)
+ {
+ WARNINGKPILOT << "Couldn't allocate memory for the exceptions" << endl;
+ dateEntry->setExceptionCount(0);
+ dateEntry->setExceptions(0);
+ return;
+ }
+
+ size_t n=0;
+
+ KCal::DateList::ConstIterator dit;
+ for (dit = exDates.begin(); dit != exDates.end(); ++dit ) {
+ struct tm ttm=writeTm(*dit);
+ ex_List[n++]=ttm;
+ }
+ dateEntry->setExceptionCount(excount);
+ dateEntry->setExceptions(ex_List);
+}
+
+
+bool KCalSync::setEvent(KCal::Event *e,
+ const PilotDateEntry *de,
+ const CategoryAppInfo &info)
+{
+ FUNCTIONSETUP;
+ if (!e)
+ {
+ DEBUGKPILOT << fname
+ << "! NULL event given... Skipping it" << endl;
+ return false;
+ }
+ if (!de)
+ {
+ DEBUGKPILOT << fname
+ << "! NULL date entry given... Skipping it" << endl;
+ return false;
+ }
+
+
+ e->setSecrecy(de->isSecret() ?
+ KCal::Event::SecrecyPrivate :
+ KCal::Event::SecrecyPublic);
+
+ e->setPilotId(de->id());
+
+ setStartEndTimes(e,de);
+ setAlarms(e,de);
+ setRecurrence(e,de);
+ setExceptions(e,de);
+
+ e->setSummary(de->getDescription());
+ e->setDescription(de->getNote());
+ e->setLocation(de->getLocation());
+
+ // used by e.g. Agendus and Datebk
+ setCategory(e, de, info);
+
+ // NOTE: This MUST be done last, since every other set* call
+ // calls updated(), which will trigger an
+ // setSyncStatus(SYNCMOD)!!!
+ e->setSyncStatus(KCal::Incidence::SYNCNONE);
+
+ return true;
+}
+
+bool KCalSync::setDateEntry(PilotDateEntry *de,
+ const KCal::Event *e,
+ const CategoryAppInfo &info)
+{
+ FUNCTIONSETUP;
+ if (!de || !e) {
+ DEBUGKPILOT << fname
+ << ": NULL event given... Skipping it" << endl;
+ return false;
+ }
+
+ // set secrecy, start/end times, alarms, recurrence, exceptions, summary and description:
+ if (e->secrecy()!=KCal::Event::SecrecyPublic)
+ {
+ de->setSecret( true );
+ }
+
+ setStartEndTimes(de, e);
+ setAlarms(de, e);
+ setRecurrence(de, e);
+ setExceptions(de, e);
+ de->setDescription(e->summary());
+ de->setNote(e->description());
+ de->setLocation(e->location());
+ setCategory(de, e, info);
+ return true;
+}
+
diff --git a/kpilot/conduits/vcalconduit/vcalRecord.h b/kpilot/conduits/vcalconduit/vcalRecord.h
new file mode 100644
index 000000000..4cad14b51
--- /dev/null
+++ b/kpilot/conduits/vcalconduit/vcalRecord.h
@@ -0,0 +1,51 @@
+#ifndef _KPILOT_VCALRECORD_H
+#define _KPILOT_VCALRECORD_H
+/* vcal-conduit.h KPilot
+**
+** Copyright (C) 2006 by Adriaan de Groot <groot@kde.org>
+** Copyright (C) 2002-2003 by Reinhold Kainhofer
+** Copyright (C) 2001 by Dan Pilone
+**
+*/
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+class PilotDateEntry;
+
+namespace KCal
+{
+ class Event;
+}
+
+namespace KCalSync
+{
+ bool setEvent( KCal::Event *e,
+ const PilotDateEntry *de,
+ const CategoryAppInfo &info);
+ bool setDateEntry(PilotDateEntry *de,
+ const KCal::Event *e,
+ const CategoryAppInfo &info);
+}
+
+#endif
+
+
diff --git a/kpilot/conduits/vcalconduit/vcalconduitSettings.kcfgc b/kpilot/conduits/vcalconduit/vcalconduitSettings.kcfgc
new file mode 100644
index 000000000..7855ad246
--- /dev/null
+++ b/kpilot/conduits/vcalconduit/vcalconduitSettings.kcfgc
@@ -0,0 +1,7 @@
+File=vcalconduitbase.kcfg
+ClassName=VCalConduitSettings
+#Singleton=true
+ItemAccessors=true
+Mutators=true
+GlobalEnums=true
+SetUserTexts=true
diff --git a/kpilot/conduits/vcalconduit/vcalconduitbase.kcfg b/kpilot/conduits/vcalconduit/vcalconduitbase.kcfg
new file mode 100644
index 000000000..c35e79074
--- /dev/null
+++ b/kpilot/conduits/vcalconduit/vcalconduitbase.kcfg
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
+ http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
+ <kcfgfile name="kpilot_vcalconduitsrc">
+ <parameter name="conduit" />
+ </kcfgfile>
+
+ <group name="$(conduit)-Conduit">
+ <entry name="ConduitVersion" type="UInt">
+ </entry>
+ <entry name="CalendarType" type="Enum">
+ <choices>
+ <choice name="eCalendarResource"/>
+ <choice name="eCalendarLocal"/>
+ </choices>
+ <default>eCalendarLocal</default>
+ </entry>
+ <entry name="CalendarFile" key="CalFile" type="Path">
+ <default>$HOME/.kde/share/apps/korganizer/std.ics</default>
+ </entry>
+ <entry name="SyncArchived" type="Bool">
+ <default>true</default>
+ </entry>
+ <entry name="ConflictResolution" type="Int">
+ <default>0</default>
+ </entry>
+ </group>
+
+</kcfg>